2011-04-26 59 views
23

我已經閱讀了大量的帖子和文章,但我無法找到明確的答案。C++,靜態與命名空間vs.單身

我有一些類似的功能,我想超出全球範圍的功能。其中一些需要公開,其他是私人的(因爲它們只是「公共」的輔助功能)。 此外,我不只有函數,而且還有變量。只有「私人」輔助功能需要它們,並且應該是私人的。

現在有三種方式:

  • 做的一切是靜態類(禁忌:潛在的「無法調用成員函數沒有對象」 - 不是一切都需要是靜態的)
  • 做一個單身類(魂鬥羅:我需要的對象)
  • 作出命名空間(沒有私人關鍵字 - 爲什麼我應該把它放在一個命名空間的話,那麼?)

,會是什麼方式,爲我取?將這些方法結合起來的可能方法是什麼?

我認爲是這樣的:

  1. 做一個單身,靜態函數使用單對象的輔助功能(這是可能的,我仍然在類中,但訪問它的一個目標是?型)
  2. 構造方法中調用PROGRAMM處開始,初始化一切( - >確保靜力學可以從單獨的對象只能通過MyClass的:: PublicStaticFunction()
訪問功能)
  • 訪問的公共職能

    謝謝。

  • +4

    不要使用單身,除非喲你真的需要(即。幾乎從不)。一個很好的討論是http://www.ibm.com/developerworks/webservices/library/co-single/index.html – 2011-04-26 16:32:25

    回答

    20

    如前所述,使用全局變量是普遍不好的工程實踐,除非絕對必要,當然(映射硬件例如,但這並不經常發生)。

    在類積攢的一切是你將在一個類似Java的語言做的,但在C++中,你不必,實際上使用的命名空間這裏是一個更好的選擇,如果只:

    • 因爲人們不會突然構建對象的實例:爲了什麼目的?
    • 因爲命名空間中不產生內省信息(RTTI)

    下面是一個典型的實施方式:

    // foo.h 
    #ifndef MYPROJECT_FOO_H_INCLUDED 
    #define MYPROJECT_FOO_H_INCLUDED 
    
    namespace myproject { 
        void foo(); 
        void foomore(); 
    } 
    
    #endif // MYPROJECT_FOO_H_INCLUDED 
    
    // foo.cpp 
    #include "myproject/foo.h" 
    
    namespace myproject { 
    
    namespace { 
        typedef XXXX MyHelperType; 
    
        void bar(MyHelperType& helper); 
    } // anonymous 
    
    void foo() { 
        MyHelperType helper = /**/; 
        bar(helper); 
    } 
    
    void foomore() { 
        MyHelperType helper = /**/; 
        bar(helper); 
        bar(helper); 
    } 
    } // myproject 
    

    匿名命名空間在源文件整齊地捲起是增強private部分:不僅客戶端無法使用裏面有什麼,但他甚至沒有看到它在所有的(因爲它是在源文件中),因此不依賴於它(其中有一定的ABI和編譯時間優勢!)

    +2

    謝謝。我認爲這是我的問題的最佳解決方案。我來自C#(所有內容都是類),這就是爲什麼這些(未命名)名稱空間解決方案對我而言是新的。 – blubberbernd 2011-04-26 19:18:54

    +0

    @blubberbernd:在這種情況下,我只能推薦一本好的C++書籍。 C++既豐富又充滿(糟糕的)意外,一個好的教程只能提供幫助。有一個SO列表:http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – 2011-04-27 06:18:41

    +0

    好的答案。我正在用C++進行一些嵌入式編程,並且遇到了一些外圍設備可以使用(應該初始化)一次的問題。在C中實現是一件很自然的事情,但我覺得我必須使用C++來實現面向對象的方法。但是使用單例的用途有限,因爲我還必須實現相關的中斷服務例程作爲「自由函數」。 – 2016-08-05 07:09:16

    2

    這樣做的傳統C方法似乎是你想要的,就是將公共函數聲明放在頭文件中,並將所有實現放在源文件中,從而使變量和非公共函數保持靜態。否則就把它作爲一個班級來實施 - 我認爲你在這裏做出了一點小小的貢獻。

    +2

    請注意,以這種方式使用'static'在C++中被棄用,以支持匿名命名空間。所以'namespace {int i; }而不是'static int i;'否則,是的。 – 2011-04-26 19:00:11

    +0

    @Dennis Stroustrup前段時間討論的是不贊成它,我認爲這是正確的做法。不知道是否有任何事情發生。我找到了無名的命名空間的東西,好吧......傻。 – 2011-04-26 19:02:56

    +1

    就我個人而言,我發現'靜態'有三個完全無關的含義。但是看看C++ 0x草案,他們似乎已經刪除了這一點。所以沒關係:-) – 2011-04-26 19:19:44

    1

    如何在全局範圍內使用關鍵字static作爲隱私替代品?

    6

    Don't make it a singleton

    對於不直接依賴於這些變量,使他們非成員函數公共輔助功能。把他們放在課堂上沒有任何好處。

    其餘的,把它放在一個普通的非靜態成員的類中。如果你需要一個單一的全球可訪問的類的實例,然後創建一個(但不要使它成爲一個單一的,只是一個全局)。

    否則,在需要時實例化它。

    +0

    Yay,匿名downvotes。任何人都在意解釋*爲什麼這是一個不好的答案? – jalf 2011-04-26 16:54:17

    +1

    我不是downvoter,但我猜一些可能會遇到問題與您的「全球可訪問的實例」段落。全局對象與單例有相同的缺點(因爲單身只是僞裝的全局對象)。 – 2011-04-26 17:13:53

    +1

    另一個爭論點可能是「把他們放在課堂上沒有任何好處」。獲得了一件事,儘管很簡單:擁有靜態成員函數的類充當命名空間。我意識到'namespace'可以實現同樣的效果,但也許來自Java背景的人不會。 – 2011-04-26 17:19:10

    0

    請記住,singleton類的單例實例是一個有效的實例,所以它完全能夠成爲非靜態成員函數的接收者。如果您將單例工廠公開爲靜態函數,那麼將所有公共功能都視爲公共非靜態成員函數,將您的私有功能視爲私有非靜態成員函數,任何能夠訪問該類的人都可以通過調用單例工廠來訪問公共功能功能。

    你沒有描述是否所有你想要的收官之功能,足以支持在同一類被作爲相關的,但如果是,這種方法可能會奏效。

    如果採取「C類」的做法,只是使用頂級的功能,你可以讓他們通過私人在.cpp文件,而不是公開,包含的.h文件中聲明它們。如果採取這種方法,你也應該使它們成爲靜態的(或者使用匿名的命名空間)。

    1

    從你的描述,它看起來像你有一個相互交流在這裏,換句話說,這聽起來像你對我其實是想非單件類,以保持狀態,並提供操作經該國的方法和數據。將公共職能作爲接口公開,並保持其他所有內容不公開。

    然後,您可以根據需要創建實例,不必擔心init的順序或線程問題(如果每個線程有一個),並且只有需要訪問的客戶端纔會有對象進行操作。如果你真的只需要其中的一個,在整個程序,你可以逃脫說,在main或可能是一個instance方法設置一個全球性的指針,但那些帶着自己套的問題。