2013-02-01 42 views
-2

注:我發現我的Xcode是如何編譯下面的問題,它似乎與此處討論的主題無關。當我有更多的細節時,我會在這裏提供。如何轉發聲明一個自定義構造函數?

我建議投票結束我的問題爲「過於本地化」,因爲它是一個Xcode問題,與C++代碼本身無關。非常感謝這些幫助,因爲我從答案中學到了東西。

下面的問題(現在回答和解決)是由於Xcode目標文件混淆排除引起的,因此即使文件有問題也沒有編譯器錯誤。


我有一個純虛擬接口,想定義它的工廠方法,它返回這個接口的子類。這工作得很好:

struct MyVirt{ 
...all virtual stuff 
}; 

class SubVirt; //forward declaration allows factory: 
MyVirt*CreateClass(){ 
return new SubVirt; 
} 

更新:一些評論說,前申報是不夠的,實現上述目標,但這是不正確的。您可以在沒有SubVirt類的完整定義的情況下完成上述罰款。

現在,我想要做的是有一個自定義構造函數,它需要參數。因此:

MyVirt*CreateClass(){ 
return new SubVirt(arg 1, etc); 
} 

問題是,class前向聲明已不夠用。它需要查看類定義或其標題。這意味着我可以將工廠方法移動到定義了SubVirt的文件中,或者我必須將該文件包含在上面的文件中,該文件會創建一個循環依賴關係。

有沒有辦法轉發聲明自定義構造函數呢?這會讓這一切變得更簡單。

+4

我有麻煩理解:'新SubVirt'也需要看到'SubVirt'的定義,對不對?所以頭部必須包含 –

+0

當返回一個指針時,編譯器需要知道具體的指針大小,所以前向聲明是不夠的。 – billz

+0

@SebbyJohanns:在'new'符*需求*看到類的定義,你不能只提供一個向前聲明。如果使用不完整的類型,它將不會編譯。所以這意味着你必須在某個地方包含一個頭文件。 –

回答

3

你的CreateClass函數看起來很奇怪,你錯過了()的函數定義。應該是這樣的:

MyVirt* CreateClass() 
{ 
    return new SubVirt(arg 1, etc); 
} 

當返回一個指針時,編譯器需要知道具體的類型和構造函數,所以forward declare是不夠的。

你可以做的是:

  • 在頭文件:轉發聲明SubVirtCreateClass功能
  • CPP文件:包括MyVirt.h和執行定義CreateClass功能
+0

這是一個錯字;固定。 – johnbakers

+0

「當返回一個指針,編譯器需要知道具體的指針」 指針的大小總是相同的。當你聲明返回一個指向結構的指針時,前向聲明就足夠了。當你實現它時,你需要完整的聲明。 – cubuspl42

+0

@SebybyJohanns,沒有意義 – billz

3

單獨的聲明一樣,每個人都會。

MyVirt.h:

struct MyVirt{ 
...all virtual stuff 
}; 

MyVirt.cpp:

#include "MyVirt.h" 
Implementation of MyVirt 

SubVirt.h:

#include "MyVirt.h" 
struct SubVirt : MyVirt { 
...all SubVirt stuff 
}; 

SubVirt。CPP:

#include "SubVirt.h" 
Implementation of SubVirt 

Factory.h:

struct MyVirt; 
MyVirt *CreateClass(); 

Factory.cpp:

#include "SubVirt.h" 
MyVirt *CreateClass() { return new SubVirt() } 
+0

我喜歡你的早期版本,其中'#include「SubVirt.h」'是76磅粗體字!但是你應該在SubVirt.h文件中真正顯示一個'#include「MyVirt.h」'。 – phonetagger

+0

我忘記了「代碼格式」:P是的,你是對的,那頭是必要的。 – cubuspl42

0

這可以通過分離聲明和實現來完成。

這裏的關鍵是把定義/實施以上的包括。假設你要分出類A和B創建兩個文件,如下所示:

A.hpp

#ifndef A_HPP 
#define A_HPP 

struct B; // fwd. decl. 

struct A { 
    int v; 
    A(int v) { 
     this->v = v; 
    } 
    B* createB(); 
}; 

#include "B.hpp" 

A* B::createA() { 
    return new A(v); 
} 

#endif A_HPP 

B.hpp

#ifndef B_HPP 
#define B_HPP 

struct A; // fwd. decl. 

struct B { 
    int v; 
    B(int v) { 
     this->v = v; 
    } 
    A* createA(); 
}; 

#include "A.hpp" 

B* A::createB() { 
    return new B(v); 
} 

#endif // B_HPP 

main.hpp

#include <A.hpp> 
#include <B.hpp> 
#include <iostream> 

int main(int argc, char *argv[]) { 
    A a(42); 
    std::cout << a.createB()->createA()->v << std::endl; 
    return 0; 
} 

您當然可以自由地將實現移動到cpp文件中。這只是顯示即使對於模板類和函數也可以如何解決循環依賴性的基本配方。

http://codepad.org/IsBzQANX

相關問題