簡體   English   中英

如何解決無法在C ++中重載返回類型的問題

[英]How to get around inability to overload on return type in C++

我有可以創建許多不同模板類型的函數; 該問題的一個簡單示例是:

EncodedMsg<?>* encode(const Msg& msg)
{
    if(msg.qty < 100) 
        return new EncodedMsg<short>(...);
    else if(msg.qty < 100000)
        return new EncodedMsg<int>(...);
    else 
        return new EncodedMsg<long>(...);
}

我的問題是:

  1. 關於模板內容的決定由功能內部決定
  2. 我不能在返回類型上重載
  3. 我不想返回EncodedMsg的基類類型,因為稍后我將不得不解碼它是什么類型的消息

誰能想到解決這個問題的方法?

您試圖以動態方式使用模板,而這是不可能的。 模板的類型必須在編譯時就已知道,因此您不能基於一系列條件進行區分。

要在運行時更改類型,您將需要類和繼承的多態性。

基本上,如果測試變量msg.qty不是編譯時常量,那么這將是不可能的。 您必須了解,模板可用於實現靜態多態性,而OOP(繼承)可用於實現動態多態性。 換句話說,模板在編譯時解析,而虛擬函數調用在運行時解析。 您可以同時使用兩者,但不能將它們用於相同的目的(即它們是互補的編程范例,每個范例都有各自的應用程序上下文)。

如果你可以,不過,得到msg.qty是類型的編譯時間常數Msg (即Msg::qty ,作為一個enumstatic const ),那么你可以使用boost::enable_if庫。 因此:

template <class Msg>
typename boost::enable_if<Msg::qty < 100, EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<short>(...); };

template <class Msg>
typename boost::enable_if<((Msg::qty >= 100) && (Msg::qty < 100000)), EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<int>(...); };

template <class Msg>
typename boost::enable_if<Msg::qty >= 100000, EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<long>(...); };

但是,對於特定的Msg類,可以確定要對EncodedMsg使用哪種模板實例化,那么將其定義為Msg類中的嵌套typedef並定義編碼函數要容易得多:

template <class Msg>
Msg::encoded_type* encode(const Msg& msg) { return new Msg::encoded_type(...); };

如果您有不可修改的消息類,也可以使用類型特征(例如message_trait或類似的東西)來定義嵌套的typedef。

但是,如果msg.qty只能是運行時值,則別無選擇,只能使用動態多態性(即,將指針返回到基類或接口)。 或者,您也可以使用boost::variant 在這種情況下,您可以執行以下操作:

boost::variant< EncodedMsg<short>,
                EncodedMsg<int>,
                EncodedMsg<long> >* encode(const Msg& msg)
{
  typedef boost::variant< EncodedMsg<short>,
                          EncodedMsg<int>,
                          EncodedMsg<long> > result_type;
  if(msg.qty < 100) 
    return new result_type( EncodedMsg<short>(...) );
  else if(msg.qty < 100000)
    return new result_type( EncodedMsg<int>(...) );
  else 
    return new result_type( EncodedMsg<long>(...) );
};

上面有一些明顯的問題(例如,結果類型將與EncodedMsg的最大模板實例化一樣大,但您可以通過附加級別的間接尋址(將指針存儲到EncodedMsg對象)解決該問題。 如果可以找到,它不如多態替代方案那么好和有效。

1)您不能重載函數的返回類型,但是可以重載傳遞給該函數的類型並通過指針傳遞。 但是,我認為這不是您想要的,請參閱2)

2)基本上,必須使用另一種設計方法來解決該問題:通過在基類中使用虛擬接口,您的方法將返回正確的類,並且僅調用適當的虛函數。 您只要返回基類(EncodedMsgBase),就可以是EncodedMsg_what,只要它是從EncodedMsgBase派生的。 您可以根據需要從基類創建模板。

在更復雜的情況下,這歸結為“如何在c ++中創建工廠”問題。 人們通常通過傳遞實現“虛擬構造函數”的基類來解決此問題。

查看c ++常見問題解答以獲取更多信息:

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8

還要記住,通過使用靜態類型可以避免很多麻煩:)

這種方法不允許您在需要進一步使用的任何地方使用EncodedMessage (因為我懷疑例如EncodedMessage<long>EncodedMessage<short>都應該可以傳遞給在EncodedMessages上運行的某些方法)。

盡管您所要求的可以通過技巧完成,但我還是建議您重新考慮您的體系結構。

您可以簡單地堅持使用EncodedMessage<long>並將其類型定義為TheOnlyPossibleEncodedMessage如果可以用於所有消息數量)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM