2010-01-27 26 views
7

我目前正在試圖將一個工廠實現爲一個單例。我實際上使用了Singleton模式的教科書示例。這裏的.h文件:C++:在Singleton類中未定義對實例的引用

namespace oxygen{ 

class ImpFactory{ 

public: 
    static boost::shared_ptr<ImpFactory> GetInstance(); 

private: 
    static boost::shared_ptr<ImpFactory> mInstance; 
}; 

和這裏的.cpp文件:

#include "impfactory.h" 

using namespace oxygen; 
using namespace boost; 

shared_ptr<ImpFactory> ImpFactory::GetInstance(){ 
    if (mInstance.get() == 0) 
     mInstance = shared_ptr<ImpFactory>(new ImpFactory()); 
    return mInstance; 
} 

代碼編譯,但我得到一個鏈接錯誤:

../../lib/oxygen/liboxygen.so.3.2.4: undefined reference to `oxygen::ImpFactory::mInstance'

這個目前有三個學生難倒。有任何想法嗎?

回答

13

您必須定義靜態實例,不只是聲明它。該定義創建您引用的實際對象。

在你cpp文件,添加一行:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
2

您需要爲一個CPP文件的靜態成員的定義。

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
2

在C++補充一點:在另一個方面說明

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
0

,也許你應該做的實例指針get函數而不是類的靜態成員,這並沒有什麼太大當你使用新的/指針方法時有很大的不同。但如果你只是創建一個靜態實例(即不使用指針,並從get get函數返回對它的引用),這會產生很大的差異,因爲:

如果它是一個類的靜態成員,其構造函數是如果它是get函數的一個靜態成員,它就不會被構造,直到它被稱爲第一次,這就緩解了人們對單例的一些問題,並且它們被全球化所美化,另一件好事是,大多數連接器會省略get函數,因此如果它永遠不會被調用,它將完全忽略靜態實例,因此您不必擔心調用new以便它只在使用時才使用內存。

0

由於您使用了Boost,因此您可能需要考慮Boost單例類。退房:

#include <boost/serialization/singleton.hpp> 

using namespace boost::serialisation; 

struct MyClass : public singleton<MyClass> 
{ string name_; int age_; }; 

int main(int argc, char* argv[]) 
{ 
    MyClass::get_mutable_instance().name_ = "Robin"; 
    MyClass::get_mutable_instance().age_ = 21; 
} 

您使用哪個取決於您正在做什麼。雖然通常情況下我有點反單身,但在可能的情況下重複使用是有意義的。儘管有一個警告:Boost單例似乎已經在庫中移動了一段時間,所以這可能取決於您使用的Boost版本。

+0

我覺得它沒有那麼多的「感動」,因爲「有人認爲他們想要一個單身人士時增加了,然後當他們意識到這畢竟不是一個好主意時就被刪除了」。 – 2010-01-27 16:23:11

相關問題