無法編譯以下內容。這裏有什麼不對?錯誤:沒有適當的默認構造函數
class B;
class A
{
public:
void DoSomething()
{
...
B* myb = new B();
...
}
};
class B
{
public:
B() {}
};
無法編譯以下內容。這裏有什麼不對?錯誤:沒有適當的默認構造函數
class B;
class A
{
public:
void DoSomething()
{
...
B* myb = new B();
...
}
};
class B
{
public:
B() {}
};
new B()
要求完整的類型定義。前向聲明是不夠的。
這是有道理的。例如,誰說B
甚至有一個公共的默認構造函數?在B
的完整定義已知之前,您無法知道。
爲了知道某些class B
存在,您做了前向聲明,儘管它尚未定義。在這種情況下,您甚至不需要這樣做,因爲B
類型的class A
中沒有成員。
剛剛宣佈doSomething
方法,後來把它定義B
定義
class A {
...
void doSomething(); // declared
...
};
class B {
...
};
// define doSomething after defining class B or in the .cpp source file
void A::doSomething() {
B *myb = new B();
...
}
後,雖然通常你會用頭/源文件,所以它會比較實用的聲明自定義分開。
編輯
如果A和B都稱呼對方,那麼你需要寫在其中的一個(或兩個)正向聲明。
// A.h
class B;
class A {
...
B *_myB;
};
// A.cpp
#include "B.h"
void A::doSomething() {
_myB = new B();
}
// B.h
class A;
class B {
...
A *_myA;
};
// B.cpp
#include "A.h"
void B::doSomething() {
_myA = new A();
}
預先聲明可以讓你有一個指針類型,如B*
。但不是完整的類型B
,因爲B
的大小未知,但B*
與任何其他指針的大小相同。
您可以通過在頭文件中包含其他類來存儲完整類型,但不能同時包含這兩種類型。
無論如何,如果您可以包含依賴完整類型,這是沒有意義的。然後,A
的一個實例將實例化成員B
,該成員又將實例化其成員A
等等。
真棒。那就是我必須做的。非常感謝您向非常簡單的技術展示燈光,並且必須記住技術。 – Anand
當你轉發聲明一個類型時,你告訴編譯器這樣一個類型exists.But編譯器不知道該類型的大小或成員。
您通常使用前向聲明來打破循環依賴關係。
class B;
class A
{
public:
void DoSomething()
{
...
B* myb ; ...
}
};
這將工作,因爲你只有一個指向該類型的指針。
這已經在這裏詳細討論: forward reference usage
class B;
上面的聲明(向前聲明)推出名稱乙到編譯器。聲明之後並且在定義出現之前,鍵入B是不完整類型。
使用不完整類型是有限的。例如,指針或引用可以定義爲這種類型。但是,這是不可能的;
在有問題的代碼中;
B* myb = new B();
是在聲明之後並且在定義出現之前。
什麼是錯誤,並把整個代碼請。 – Bill
在創建它的一個實例之前,'B'的完整定義需要可見。單靠前向宣言是不夠的。 –
C2512是錯誤代碼。 「'B':沒有適當的默認構造函數可用」@Igor Tandetnik - 我想你是對的。但如何解決這個問題? – Anand