2010-02-25 62 views
4

鑑於一類像這樣的一個成員模板函數:C++中成員模板函數的用法是什麼?

template <typename t> 
class complex 
{ 
public: 
    complex(t r, t im); 
    template<typename u> 
    complex(const complex<u>&); 
private: 
    //what would be the type of real and imaginary data members here. 
} 

我感到困惑的成員模板函數,請提供通過其成員模板函數的需求變得清楚,我舉一個例子。
另外,告訴我在C++中使用成員模板函數,我們使用成員模板函數的情況是什麼?

+1

格式化您的問題並縮進代碼時請格外小心。 – avakar 2010-02-25 18:12:23

回答

3

成員函數模板的一般用途和功能與普通(非成員)函數模板沒有任何區別。唯一的[不相關的]區別是成員函數可以訪問隱含的this參數。

您瞭解普通函數模板的一般用途嗎?那麼,在這種情況下,您應該瞭解成員函數模板的一般用途,因爲它完全相同。

+0

謝謝你的回答有幫助 – 2010-02-25 20:14:19

5

它給你做轉換的能力:

complex<int> ci; 

complex<float> cf(ci); 

所以,如果你有兩個類型T1和T2,你可以一個T1分配到T2,這將有可能爲complex<T1>分配給一個complex<T2>

至於在你的代碼的問題(這將是實部和虛數據成員,這裏的類型):

template <typename t> 
class complex 
{ 
... 
private: 
    t real_part; 
    t imaginary_part; 
}; 
+0

這不是模板成員函數的圖示。 – 2010-02-25 18:17:35

+0

請提供一個例子,除了複雜的類,我們需要使用成員模板函數 – 2010-02-25 18:18:52

+0

這不是一個實現,但它是一個例子,給定了提問者的頭文件。 – 2010-02-25 18:19:49

1

使用你提供的例子,成員模板函數可以構建的一個實例complex<T> from complex<U>

作爲什麼時候這可能有用的具體示例,假設您有complex<double>但想要complex<float>。沒有構造函數的類型是不相關的,所以常規的拷貝構造函數不起作用。

4

我在日常工作中遇到的成員模板函數最常見的有用用法是通過提供一個模板函數而不是執行基本相同的功能的許多函數來降低代碼複雜度。

例如,假設您正在一臺服務器上工作,該服務器接收半打相關的消息,並將傳入的數據保存到數據庫中的半打表中。一個簡單的實現將實現6個消息處理函數(psudocode):

class MessageProcessor 
{ 
    void OnMessage(const char* msg); 
    void ProcessMessage100(Data100* data); 
    void ProcessMessage101(Data101* data); 
    void ProcessMessage102(Data102* data); 
    void ProcessMessage103(Data103* data); 
    void ProcessMessage104(Data104* data); 
    void ProcessMessage105(Data105* data); 
}; 

MessageProcessor::OnMessage(const char* msg) 
{ 
    unsigned int * msgType = ((unsigned int*)msg); 
    switch(*msgType) 
    { 
    case 100 : 
     ProcessMessage100((Data100*),sg); 
     break; 
    case 101 : 
     ProcessMessage101((Data101*),sg); 
     break; 
    :: 
    } 
} 

MessageProcessor::ProcessMessage100(Data100* data) 
{ 
    Record100* record = GetRecord100(key); 
    record->SetValue(xyz); 
} 

MessageProcessor::ProcessMessage101(Data101* data) 
{ 
    Record101* record = GetRecord101(key); 
    record->SetValue(xyz); 
} 

: : 

這裏有一個機會來概括ProcessMessage的()函數,因爲它們基本上做同樣的事情:

class MessageProcessor 
{ 
    OnMessage(const char* msg); 

    template<class Record, class Data> void Process(Data* data); 
}; 

template<class Record, class Data> 
void MessageProcessor::Process<Record,Data>(Data* data) 
{ 
    Record* record = GetRecord(key); 
    record->SetValue(xyz); 
} 

GetRecord函數也可以進行通用化處理,產生一個代碼庫,其中有兩個函數,以前的版本是12.這改進了代碼,因爲它更簡單,移動部件更少,更易於理解和維護。

0

通常你會希望你的類的某些成員函數在一個範圍上進行操作。通過使用模板化的成員函數,您可以在不提供免費功能的範圍內獨立於提供範圍的容器進行操作。

Functors也是如此。通常你會寫一個函子來操作一些特殊的迭代器,但很快就意識到可以讓Functor在任何類型的範圍上運行。因此,可以通過成員函數操作符()來提供它們,而不是通過封裝結構提供模板參數,並使類型推斷成爲可能。

0

浮現在腦海中的第一個例子:

  • 在一些容器構造(或分配方法)取未知類型的輸入迭代。

  • std::complex允許在不同的類型上操作std::complex實例化的類型。

  • shared_ptr(是否std::tr1::boost::),這樣就可以保持不同類型的指針到在堆共享對象實例(其可以得到的指針類型)。

  • thread(是否std::在C++ 0x或boost::中)接收將由線程實例調用的未知類型的函子。

在所有情況下,使用情況都是相同的:您有一個功能可以對未知類型進行操作。正如AndreyT完美地表述的那樣,以及常規功能。