2011-03-27 30 views
7

我在混合使用Objective-C和C++。但是我想盡量減少使用Objective-C++。因爲它在Objective-C和C++中都有一些限制。推薦使用Objective-C++最小化Objective-C類的C++類的方法?

目前,我正在使用它。

// A.h, Objective-C 
#import "B.h" 
@interface A 
{ 
    B* b; 
} 
@end 

// B.h, Objective-C++ 
@interface B 
{ 
    void* c; 
} 

// C.h, C++ 
class C 
{ 
}; 

我想包括在B.hC.h,但如果我做到了,B.h不能導入A.h。所以我必須保留變量cvoid*類型。這不是一個大問題,因爲我可以在B.m文件中免費使用C的成員。但我總是必須施放它。這感覺不清楚。所以我想用更好的方法,如果是的話。

回答

15

有幾種方法可以做到這一點,但在我看來,最好的方法是使用'PIMPL' idiom,這在C++中非常常見。使標題純粹爲Objective-C和純C++,並指向包含實際實現的前向聲明結構。這是在.mm文件中定義的,然後可以使用Objective-C++。

在你的榜樣,你會做這樣的事情:

// B.h, pure Objective-C: 
struct BImpl; 
@interface B 
{ 
    struct BImpl* impl; 
} 
// ... 


// B.mm, mixed: 
#include "C.h" 
struct BImpl // since this is C++, it can actually have constructors/destructors 
{ 
    C* my_c; 
    BImpl() : my_c(new C) {} 
    ~BImpl() { delete my_c; my_c = NULL; } 
}; 
// make sure to alloc/initialise impl (using new) in B's init* methods, 
// and free it (using delete) in the dealloc method. 

其實我已經寫在正好解決這個問題的文章,你可能會發現它有用:http://philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects - 這也顯示了一些其他的方法這樣做,包括你的原始void*的方法。

+4

我不能等待剩下的4分鐘選擇這個答案! – Eonil 2011-03-27 11:01:10

4

由於pmjordan在his blog article中寫道,@interface聲明中的BImpl需要'struct'關鍵字,如下所示。

struct BImpl; 
@interface B 
{ 
    struct BImpl* impl; 
} 

我覺得他不經意間就把這個漏掉了。如果你有很多* .m文件需要包含這個頭文件,這就會產生巨大的差異。添加的'struct'關鍵字使Objective-C編譯器將此頭文件理解爲純C文件,用於導入此頭文件的其他.m文件。否則,其他導入該頭文件的* .m文件將不會被編譯。這個小小的解決方案可以讓您將* .m文件更改爲.mm文件。有時,將原始.m文件更改爲.mm會導致大量編譯錯誤。

+0

你能添加一個鏈接pmjordan的博客文章嗎? – Stephan 2012-10-02 08:00:50

+0

是的,我做到了。事實上,pmjordan是這個問題的第一個答案的作者。我從原始答案中獲得了鏈接。您也可以在他的回答中使用原始鏈接。 – DuncanSungWKim 2012-10-02 08:20:57

+1

此答案已合併到第一個答案中。我非常感謝@pmjordan在發佈此答案後採納我的建議。 – DuncanSungWKim 2012-10-03 05:24:45