2010-09-12 24 views
2

我是一名試圖編寫一些C++的PHP開發人員。C++ OOP基礎知識(將對象指定爲成員)

我在分配對象作爲另一個對象的屬性時遇到了問題。在PHP中,我會這樣寫:

class A { 
    public $b; 
} 
class B { 

} 

$a = new A; 
$a->b = new B; 

我該如何在C++中做到這一點?我到目前爲止:

class A { 
    B b; 
public: 
    void setB(&B); 
}; 
class B { 

}; 

void A::setB(B &b) 
{ 
    this->b = b; 
}; 

A * a = new A(); 
B * b = new B(); 
a->setB(b); 

我在做什麼錯?

+12

你有[一個很好的入門C++的書?(http://stackoverflow.com/questions/388242/the-definitive-c++-book-guide-and-list)PHP和C++是真的沒有什麼相似和不一本好書,你會發現它很難(最好)學會編寫好的,正確的C++代碼。 – 2010-09-12 19:40:26

+1

你絕對需要一本好書或C++的這種學習材料。特別是您需要了解C++如何處理指針,引用和對象實例。大多數解釋型語言使這些細節無關緊要,或者在大多數時候以其他方式管理它們,但在C++中,這些概念恰到好處。 – TheUndeadFish 2010-09-12 22:05:51

+0

@詹姆斯:我寧願說,如果沒有一本好書,他永遠不會寫出好的C++代碼,只是將一些代碼行放在一起。我還想補充說,自己學習是非常困難的,如果他有一個導師(一個好的......)來解釋事情,那將是最好的。當然SO可以幫助太:) – 2010-09-13 08:36:24

回答

1

一對夫婦的變化將使其編譯:
1類B需要,以便它可以在以前是之前聲明A類
2.聲明組​​B(& B)需要組B的微小變化(B &)

class B { 
}; 

class A { 
    B b; 
public: 
    void setB(B&); 
}; 
void A::setB(B &b) 
{ 
    this->b = b; 
}; 

int main() 
{ 
A * a = new A(); 
B * b = new B(); 
a->setB(*b); 
} 

爲了使它更有效地考慮加入以下構造接受乙作爲參數和初始化該成員變量'b'。這將在'b'成員變量上使用複製構造函數,而不是使用默認構造函數和賦值運算符。

A(B& b_) : b(b_) 
{ 
} 
+0

你的代碼仍然不能編譯,(你是給一個指針,需要一個參考,而不是一個函數),如果它會,內存泄漏仍然會在那裏。 – Jasper 2010-09-12 23:03:51

+0

@Jasper - 行'a-> setB(b)'實際上是問題的原始代碼。我剛糾正了方法的簽名(在'錯誤位置'有'&')。我將添加一個'*'來編譯它。謝謝 – skimobear 2010-09-13 00:00:19

2
  1. 而不是&B,你的意思是B&

    class A { 
        B b; 
    public: 
        void setB(B&); //<-- 
    }; 
    
  2. 指針不能隱式取消引用。所以a->setB(b)不會編譯。你需要寫a->setB(*b)

  3. 您不需要new構造一個對象。例如,這個工程:

    A a; 
    B b; 
    a.setB(b); 
    
  4. 不要直接在C使用其他語言的成語++。例如,setters和getters很少需要。事實上,你的A類可能只是一個簡單的結構。

+0

雖然目前還不清楚爲什麼你會露出這樣的功能,你的'組B()'函數應該採取它的參數或者通過值('組B(B)')或* const的*參考('setB(B const&)')。 – seh 2010-09-13 00:21:53

6

只是這樣做:

class B 
{ 
}; 

class A 
{ 
    B b; 
}; 


int main() 
{ 
    A anA; // creates an A. With an internal member of type B called b. 

    // If you want a pointer (ie using new. 
    // Then put it in a smart pointer. 
    std::auto_ptr<A> aPtr = new A(); 
} 

你實際上並不需要單獨創建B中。 B b是該類的一部分,並在創建A對象時自動創建(使用默認構造函數)。單獨創建兩個對象,然後將它們組合起來是一個不好的主意。

如果您想在構造B對象時傳遞一些參數。這是很容易通過創建一個構造函數調用B的構造函數來做到:

class B 
{ 
    public: 
     B(std::string const& data) // The B type takes a string as it is constructed. 
     :myData(data)    // Store the input data in a member variable. 
     {} 
    private: 
     std::string myData; 
}; 
class A 
{ 
    public: 
     A(std::string const& bData) // parameter passed to A constructor 
      :b(bData);    // Forward this parameter to `b` constructor (see above) 
     {} 
    private: 
     B b; 
}; 

int main() 
{ 
    A a("Hi there"); // "Hi there" now stored in a.b.myData 
} 
0

有很多的東西錯這個代碼:

  • 作爲KennyTM筆記,連字符是在錯誤的地方。
  • 您正在傳遞一個B *到一個需要B &的函數,它們在C++中不一樣
  • 您的php片段中顯示的設計似乎設計錯誤。雖然你正在做的事情是你可能想要做的事情,但你通常會想使用一個構造函數,而不是C++和PHP。
  • 你直接把代碼中的文件,這是不是在C++允許,把它的主要功能,而不是
  • 內存管理:您正在使用new沒有delete(或智能指針類)
  • 你使用B類A類,而A類不知道關於B類(它是後面定義) - 你應該穿上頂級B(或者可能使用前聲明)

幾個方法讓你的代碼正常工作如下所示。

include <memory> 
using std::auto_ptr; 


class B 
{ 
} 

class A 
{ 
public: 
    A(); 
    SetB(B& b); 

private: 
    B b1; // a B made in the constructor 
    B b2; // a COPY of the original B you make 
} 

A::A() 
    : b1(/*whatever you want to pass to B's constructor*/) 
{ 
} 

A::SetB(B& b) 
{ 
    b2 = b; 
} 

int main(int agrc, char** argv) 
{ 
    A firstA(); 
    B firstB(); 

    firstA.SetB(firstB); 

    A* secondA = new A(); 
    B* secondB = new B(); 

    secondA->SetB(*secondB); 

    auto_ptr<A> thirdA(new A()); 
    auto_ptr<B> thirdB(new B()); 

    thirdA->SetB(*thirdB); 

    // whatever other code 

    delete secondA; 
    delete secondB; 
} 

注意ID調用SETB只有一次(而且是與你所創建的不同對象之間的循環depndencies沒問題),但你希望類的外部構造B的靈活性,可以改爲構造函數的參數。

另外請注意,你正在製作一個你在main中創建的B的副本 - 如果你想在類中使用傳入副本(就像你在PHP中一樣),你應該使用成員引用(在這種情況下,你將需要設置它在構造函數中引用的內容,但在SetB函數中不能這樣做。

然後,請注意,secondA,secondB方法存在嚴重問題,因此不建議但是,沒有什麼會出錯的,但是,這樣很容易獲得泄漏內存的代碼(並且很難找出泄漏的位置),並且最重要的是,當您要使用異常時,您需要異常安全代碼,這是不能達到使用普通的舊的指針。

最後,請注意你在這裏混搭。例如,一起使用firstA和thirdB沒有任何問題。