2011-04-16 86 views
3

有關在C++類中有條件地定義成員函數的建議是什麼? (這個問題集中在限制DLL中某些類的外部暴露 - 特別是當這些類作爲參數傳入時)。顯然,這不是你想要對數據成員做的事情,但功能應該沒問題吧?有條件成員函數

例如:

class A 
{ 
public: 
    void func1(); 

#ifdef _CONDITION_ 
    void func2(B b); 
#endif  
}; 

編輯: 新增公共修改,以避免混淆例子。

+0

你能否詳細說明你爲什麼要這樣做? #indef(預處理器)是一個編譯前的東西,所以你不能用它來使成員函數在某些調用中出現,而不是在其他調用中出現。 – seand 2011-04-16 02:24:34

+0

使用C++中的共享庫(DLL)時,通常還包含在庫中編譯的類的頭文件。在這種情況下,我不希望使用DLL的軟件看到這些頭文件中引用的一些類。 – Nicholas 2011-04-16 02:28:36

+0

oic;你正在創建不同風格的頭文件,一個用於內部使用,另一個用於外部接口?這聽起來像你的技術會很好。如果這與您的需求類似,我已經看到#if控制是否像__declspec(dllexport)這樣的東西被髮射的情況。 – seand 2011-04-16 02:32:53

回答

2

通常,如果您不想公開某個導出類的某些部分,那麼您應該考慮不公開該類的選項,而是提供一個類來繼承的抽象接口。

例如。

class AbstractExportedInterface 
{ 
public: 
    virtual void do_stuff() = 0; 
}; 

class HasStuffIDontWantToExport : public AbstractExportedInterface 
{ 
public: 
    void do_stuff(); 
    void do_other_stuff_that_i_dont_export(); 
}; 

那麼你會操作您所提供HasStuffIDontWantToExport *的DLL用戶的假設,他們只有頭的AbstractExportedInterface。

編輯:迴應的第一個評論

如果您希望您的DLL的客戶端能夠以某種方式使用某些類型的(第三方或其他方式),但你不希望他們有充分的訪問這些類型,並且您不具有使用直接繼承層次來創建抽象接口的靈活性。您可能可以使用pimpl模式爲您希望客戶端限制使用的每種類型創建代理接口?

例如。

class ExportedAbstractProxyObject 
{ 
public: 
    virtual void do_stuff() = 0; 
}; 


#include <3rdPartyType.h> 

class ProxyObject 
{ 
public: 
    void do_stuff() { pimpl_.actually_do_stuff(); } 
private: 
    3rdPartyType pimpl_; 
}; 


class ExportedAbstractProxyOtherObject 
{ 
public: 
    virtual void do_stuff_with_thing(ExportedAbstractProxyObject* thing) = 0; 
}; 


class ProxyOtherObject 
{ 
public: 
    void do_stuff_with_thing(ExportedAbstractProxyObject* thing) { thing->do_stuff(); } 
}; 

,那麼你可以愉快地導出任何你喜歡的界面,並且完全隱藏你的DLL中實現和第三方類型。缺點是你顯然必須創建所有這些代理對象接口。

+0

我喜歡繼承方法,但它並不總是你控制的東西。例如,當創建的DLL鏈接到由第三方創建的靜態函數庫時。 – Nicholas 2011-04-16 02:50:28

2

不完全確定你在問什麼,但如果成員函數是爲了私人的類使用'私人:'關鍵字,使他們私人。

如果相反,它們的目的是爲其他類在類所在模塊的上下文中使用,但不希望外部實體知道它們,請將它們公諸於衆,但從「接口」派生類'基類,並將該接口基類暴露給外部實體。

+0

嗯,但不幸的是,'private'關鍵字並沒有阻止應用程序在編譯時從'需要'成員函數參數的完整定義鏈接到DLL。同樣使用'private'關鍵字限制瞭如何在數據包內使用該成員函數。 – Nicholas 2011-04-16 02:53:00

0

這種事情一般使用public/protected/private聲明,並可能friend S,而不是預處理條件下進行。但是在一個我寫過的程序中,將一些特定的函數聲明爲private或protected(因爲需要訪問它們的獨立函數的數量)是一個問題,我在前綴僞私有函數帶有下劃線的名稱(以及明確解釋原因的明確意見),以向讀者明確說明這些功能不適合一般用途。

+0

是的,但有了下劃線,您仍然必須定義這些函數中使用的類型。因此,必須向DLL的用戶提供更多的頭文件或轉發聲明。我真的只想提供說2頭文件,而不是60. – Nicholas 2011-04-16 03:02:28

0

你說你想阻止某些類的可見性,但是你的例子只隱藏了一個方法。

如果一個類不構成DLL的「公共」接口的一部分,則不需要發佈標頭。例如:

// foo.h 
class Bar; 

class Foo 
{ 
    private Bar* _bar; 
    ... 
} 

這裏「Bar」是實現的一部分,所以不需要發送它的頭文件。如果Bar僅由Foo使用,您也可以在Foo的private/protected範圍內定義它。

+0

不幸的是,在我的情況下,我寧願公開條件編譯的函數。 – Nicholas 2011-04-16 02:57:16

+0

然後我會推薦Vusak的方法。 使客戶端依賴於接口或抽象類是控制反轉(IoC)的基礎,並允許您編寫可輕鬆進行單元測試的高度模塊化代碼。 – David 2011-04-16 03:09:48