2010-06-23 37 views
2

我有一個接口實現的中央列表,並希望派生類能夠在列表中註冊自己,而無需將它們添加到某個中心位置。例如:在中央列表中註冊派生類

// interface.h 
struct MyInterface; 
std::vector<MyInterface*>& InterfaceList(); 

struct MyInterface { 
    MyInterface() { 
     InterfaceList().push_back(this); 
    } 
    virtual ~MyInterface() {} 
    // ... 
}; 

// derived.cpp 
#include "interface.h" 
class MyImplementation: public MyInterface { 
public: 
    MyImplementation() { 
    } 
    // ... 
}; 

MyImplementation impl; 

這似乎不起作用。由於我不明白的原因,MyInterface的構造函數永遠不會被調用 - 我會認爲派生類的實例會在啓動時調用它。我知道可以沿着這些方向做些事情,因爲我已經看到了其他庫這樣做 - 但還沒有設法弄清楚我做錯了什麼。

謝謝:)

編輯:對不起,錯過了對大括號和參考的。 InterfaceList()是一個函數,它返回一個向量的引用。

編輯第2部分:現在已經在一個簡化的例子中工作,但無法讓它在派生實現的文件中工作 - 但該技術正在另一個項目中工作。這些文件中必然會有一些細節上的差異,但這似乎不是我發佈的代碼中的問題。雖然我不想真的想張貼僱主項目的大片,所以我想我必須不停地擺弄自己。感謝您的建議,到目前爲止雖然:)

+0

你的虛擬dtor在哪裏?你需要一個在你的基類。 – 2010-06-23 04:42:23

+0

Anders:我正在嘗試發佈代碼的簡化版本,因此也留下了一些小部分。爲了討論的目的,我不在乎它是否泄漏內存:) – Peter 2010-06-23 04:55:20

回答

1

這是問題:

std::vector<MyInterface*> InterfaceList(); 

應該

std::vector<MyInterface*> InterfaceList; 
2

您例如在VS2008不能編譯。你使用什麼編譯器?當您將interface.h中的第二行更改爲

std::vector<MyInterface*> InterfaceList; 

它可以正常工作。只需放下大括號。

1

繼InterfaceList的定義是一種函數聲明,它返回的std ::矢量

std::vector<MyInterface*> InterfaceList(); 

更改爲

std::vector<MyInterface*> InterfaceList; 
2

我最近有一個類似的問題,發現最簡單的辦法是創建一個模板化的基類,負責註冊我的所有實現。

基類包含一個模板類型爲T的靜態變量,並且它已在中央列表中註冊。在運行時,每個實現都會創建自己的靜態對象,並且在創建過程中會註冊到中心列表。

#include <iostream> 
#include <vector> 

class ITestInterface 
{ 
    public: 
     virtual void Execute() = 0; 
}; 

std::vector<ITestInterface *> InterfaceList; 

template <class T> class BaseClass : 
    public ITestInterface 
{ 
    public: 
     virtual void Execute() = 0; 

    protected: 
     BaseClass() 
     { 
      InterfaceList.push_back(&s_thing); 
     } 

    private: 
     static T s_thing; 
}; 

template <class T> T BaseClass<T>::s_thing; 

class ImplementationOne : 
    public BaseClass<ImplementationOne> 
{ 
    public : 
     ImplementationOne(): 
      BaseClass() 
     { 
      ; 
     } 

     void Execute() 
     { 
      std::cout << "ImplementationOne Execute\r\n"; 
     } 
}; 

class ImplementationTwo : 
    public BaseClass<ImplementationTwo> 
{ 
    public : 
     ImplementationTwo(): 
      BaseClass() 
     { 
      ; 
     } 

     void Execute() 
     { 
      std::cout << "ImplementationTwo Execute\r\n"; 
     } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::vector<ITestInterface *>::iterator it = InterfaceList.begin(); 
    for(; it != InterfaceList.end(); it++) 
    { 
     (*it)->Execute(); 
    } 
} 

這段代碼要記住的一點是,線

static T s_thing; 

不會導致一個s_thing,而是因爲模板是一種類型的發電機有一個靜態s_thing每個派生類。

輸出是

ImplementationOne執行

ImplementationTwo執行

這個代碼在VS2010。