2013-12-19 134 views
2

所以在你開槍給我說這是一件可怕的事情之前,我只想說明我想知道這只是爲了好奇和可能代碼縮減。我想要一個爲派生類實現單例的基類。但是,這樣做會導致派生類丟失數據。我怎樣才能讓基類實現派生類的單例。例如:創建一個實現派生類的單例的基類

class Application{ 
public: 
/** 
* @brief instance: C++11 [If control enters the declaration concurrently while the  variable is being initialized, 
*the concurrent execution shall wait for completion of the initialization.—§6.7 [stmt.dcl] p4] 
* @return handle to application 
*/ 
static Application& instance(){ 
    static Application s_Application; 
    return s_Application; 
} 

void setName(std::string Name){ 
    AppName=Name; 
} 

std::string getName(){ 
    return AppName; 
} 
virtual ~Application(){ } 

private: 
Application(){} 
std::string AppName; 
}; 

現在我創建一個派生類繼承於Application:

class Test:public Application{ 
    public: 
    void printer(std::string test){ 
     std::cout<<"test\n"; 
    } 
}; 


int main(int argc, char *argv[]) { 
    Application test1=Test::instance(); 
    //Test test2=static_cast<Test>(test1); 
    test1.setName("bla"); 
    test1.printer(test1.getName()); 
} 

所以預期測試1不能調用.printer()方法,因爲返回的對象的類型是「應用程序」。有沒有辦法將派生類的類型傳遞迴主類並創建派生類的實例?

編輯:我已經使用CRTP傳遞價值了起來,但是當我做了以下這不等於對方:

Test test1=Test::instance(); 
Test test2=Test::instance(); 
cout<<"Is test1 the same as test 2? "<<(&test1==&test2)<<endl; 

這樣做的結果總是FALSE

+0

模板化的論點浮現在腦海。 – Warty

+0

CRTP ... http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern –

+0

謝謝你們,我試過CRTP路線,這是一個好主意。唯一的問題是,我必須將應用程序的構造函數移動到受保護的成員,否則我得到這個:「無標題4.cpp:9:24:錯誤:調用隱式刪除的默認構造函數'Test'static Derived s_Application;」 。這對於單身人士來說似乎是一個糟糕的主意。思考? – bge0

回答

5

您還需要將複製構造函數和賦值私有,以便不能複製對象(因爲只有對象必須存在)。

在你的代碼

Test test1=Test::instance(); 
Test test2=Test::instance(); 

你實際上是調用

Test test1(Test::instance()); 

這實際上是調用

Test (const Test &); 

這是拷貝構造函數,從而創建對象的副本。而且你實際上是在創建兩個不同的對象。這就是爲什麼地址不同。

因此,使複製構造函數和賦值運算符是私人的,以便沒有人可以複製它。

,並使用以下

Test & test1 = Test::instance(); 
Test & test2 = Test::instance(); 

在這種情況下,地址是一樣的。

如果需要,您也可以返回指針Test::instance

+0

完美,就是這樣,謝謝! – bge0

相關問題