2017-10-07 88 views
0

我們正在設計一個新系統,我們已經爲大多數類創建了接口,以便我們可以爲它們創建模擬(谷歌模擬)以進行單元測試。因此,所有的功能都是虛擬的,但問題是我經常遇到模板虛擬功能問題。我已經看到了一些關於如何進行多派遣的例子,但他們似乎都在使用模板的一些變體,這似乎並不簡單。那麼這是否意味着我的整個代碼庫現在最終會導致模板難以讀取/使用和調試?由於基於接口的編程而陷入C++虛擬模板功能問題

或者我沒有設計好的接口。這裏是一個簡單的例子,我正在爲消息隊列寫一個接口。

Class IMessageQueue { 

    Public: 

    Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type 

}; 

Class MessageQueue : public IMessageQueue { 
     Public: 

     Virtual int send(const T & value) { ... } 
}; 

Class MockMQ : public IMessageQueue { 
     Public: 
     Virtual int send(const T & value) { 
       // mock implementation 
      } 
}; 

我該如何解決這個問題?這只是一個例子,但由於基於接口的編程,我遇到了很多這類問題。

+0

你也許可以得到解決他們通過使它們不是虛擬的,並具有一個輔助函數,通過dynamic_cast確定類型,然後調用該特定類型的模板成員函數。我不知道它會在你的具體情況下變得多麼醜陋和難以忍受,我也從未嘗試過。 – Sopel

回答

0

這取決於您是否需要您的IMessageQueue調度特定的未知類型或任何類型。這不是一回事。

特定未知類型可以通過

template<typename T> 
class IMessageQueue { 
public: 
    virtual int send(const T& value); 
} 

進行管理,這樣你可以有你IMessageQueue<MyMessage>IMessageQueue<OtherMessage>

相反,如果你需要能夠與同一類型的消息隊列發送任何類型,那麼你的選擇是聲明所有的消息一個特定的接口,如

class Message 
{ 
protected: 
    Message() : { .. } 
}; 

class MyMessage : public Message 
{ 
.. 
}; 

class MessageQueue 
{ 
public: 
    void send(const Message& message); 
}; 
+0

謝謝傑克。如果IMesageQueue是一個模板類,那麼發送不能再是虛擬的,不是?我更喜歡第二種解決方案,但這是否意味着我每次需要發送新類型的數據時都需要創建一個新的消息類型子類?我想創建一個庫並將其公開,以免我經常更改庫。我們可以將消息作爲模板,但我認爲我們會再次回到同樣的問題,因爲IMessage send()方法將採用Mesage ,這將再次不允許我們發送虛擬。 – maverick112