2016-10-20 14 views
0

我試圖設計一個庫,只打開幾個接口來調用,而不會弄亂它自己的內部訪問控制。什麼是正確的方法來做到這一點?如何正確設計圖書館的外部訪問而不搞亂內部訪問?

例如,這裏是圖書館:

namespace ControlledLib { 
    class ThinkTrack1 { 
     friend class DeepThought; 
     friend class ThinkTrack2; 
    private: 
     int ResultA() { return 6; } 
     int ResultB() { return 5; } 
    }; 

    class ThinkTrack2 { 
     friend class DeepThought; 
    private: 
     int ResultC() { ThinkTrack1 tt1; return tt1.ResultB() + 2; } 
    }; 

    class DeepThought { 
     friend int DeepThoughtAnswers(); 
    private: 
     int Answers() { 
      ThinkTrack1 tt1; 
      ThinkTrack2 tt2; 
      return tt1.ResultA() * tt2.ResultC(); 
     } 
     int CreateWorld() { 
      return 7; 
     } 
    }; 

    int DeepThoughtAnswers() { DeepThought dt; return dt.Answers(); } 
} 

,它可以通過

#include "ControlledLib.h" 

int i = ControlledLib::DeepThoughtAnswers(); 

被稱爲實際的答案被class DeepThought的功能Answers()給出,但是,僅做一個Answers()訪問外部來電者,我必須使class DeepThought的功能私人,併發明一個全球功能DeepThoughtAnswers()作爲條目p oint,其中調用class DeepThought得到答案,則class DeepThought必須將DeepThoughtAnswers()定義爲的朋友函數。

它剛剛開始。作爲class DeepThought實際上調用class ThinkTrack1class ThinkTrack2,並且class ThinkTrack2電話class ThinkTrack1等等......要把這些不可訪問外部調用程序,所有這些功能都設置爲私人,我必須定義很多朋友船。最重要的是,所有這些搞砸了內部訪問控制!

什麼是更好的方法來做到這一點?

回答

1

在設計接口時,您可以選擇一些選項。首先是定義一個可以導出一組函數的C接口。這些函數在內部調用你的類,它們通過這個層隱藏起來。

<ControlledLib.h> 
extern "C" int DeepThoughAnswers(); 
</ControlledLib.h> 

在源文件中的你有此功能的實現:你在這個源包括然後用知名度不friend,你只船產生的庫和ControlledLib.h文件

<ControlledLib.cpp> 
#include "DeepThought.h" 
#include "ThinkTrack1.h" 
#include "ThinkTrack2.h" 

int DeepThoughAnswers() 
{ 
    DeepThought dt; 
    return dt.Answers(); 
} 
</ControlledLib.cpp> 

的文件。

另一種方法是使用C++接口來隱藏實現細節。這裏談到的接口:

<ControlledLib.h> 
class ControlledLib 
{ 
public: 
    virtual int DeepThoughAnswers() = 0; 
}; 
</ControlledLib.h> 

然後你有這個接口的實現,這可能是這樣的:

<MyControlledLib.h> 
class MyControlledLib : public ControlledLib 
{ 
public: 
    virtual int DeepThoughAnswers(); 
    void someOtherFunction(); //<-- not visible to the 'outside' 
}; 
</MyControlledLib.h> 

而且你添加一個工廠,允許客戶端來實例庫。

<ControlledLib.h> 
#include "ControlledLib.h" 

class MyControlledLibFactory 
{ 
public: 
    static MyControlledLib* create(); 
}; 
</MyControlledLib.h> 

給客戶端只發運工廠和界面,其他一切都隱藏起來。 到目前爲止,您的接口只使用原始類型,這意味着您不必導出其他任何東西。如果你想在你的界面中使用類,你也需要導出這些類的用法。

<ControlledLib.h> 
class ControlledLib 
{ 
public: 
    virtual int DeepThoughAnswers() = 0; 
    virtual ComplexAnswer* DeepThoughAnswersAreComplex() = 0; //<-- ComplexAnswer header needs to be supplied too. 
}; 
</ControlledLib.h> 
1

我建議你使用更多受保護的關鍵字,並減少使用好友關鍵字,並重新設計界面,因爲它看起來很凌亂。實現和接口的橋接設計模式將會很好,您可以將實現作爲庫隱藏起來,並僅將接口作爲頭文件進行分發。

+0

作者:「將實現隱藏爲一個庫並僅將接口作爲頭文件分發」,是否意味着我可以將它分解爲'ControlledLib.h'和'ControlledLib.cpp',並且只有暴露的東西在ControlledLib.h頭文件中可以訪問調用者? – athos