2013-02-24 31 views
0

我想將一個類從「普通」類轉換爲模板類,但我不明白正確的語法。下面是一個(大大簡化)我開始的例子。這是Visual Studio 2010,C++,面向x64體系結構,Windows 7。如何將「正常」C++類轉換爲模板?

目標是將類T重寫爲模板,以處理TEntry或類TEntry的新類,OtherTEntry,具有相同的成員函數,但具有不同的數據成員。

我很感謝關於如何做到這一點的建議。如果可能的話,我想將頭文件和實現文件分開。我特別堅持對局部變量T *的引用,以及如何正確使用sizeof()。

在文件釷:

class T 
{ 
    T(void); 
    T(G *pGIn, const unsigned long s, char nIn); 
    ~T(void); 

    // Member functions 
    public: 
    bool Expand(const unsigned long newS); 
    void Empty(void); 

    private: 
    G *pG; 
    char n; 
    unsigned long s; 
    int f; 
    TEntry *p; 
}; 

在文件TEntry.h:

class TEntry 
{ 
    // Constructors 
    public: 
    TEntry(); 
    TEntry(int l); 

    // Member functions 
    public: 
    void Relocate(int delta); 

private: 

    // Data members 
    int k; 
    TEntry *p; 
}; 

在文件T.cpp:

T::T() 
{ 
    p=NULL; s=0; pG=NULL; 
    Empty(); 
    return; 
} 

T::T(G *pGIn, const unsigned long m, char nIn) 
{ 
    pG=pG; n=nIn; 
    return; 
} 

T::~T(void) 
{ 
    if(p!=NULL) 
     delete[] p; 
    return; 
} 

bool T::Expand(const unsigned long newS) 
{ 
    T *pBefore=p; 
    p=(T *)_realloc_dbg(p, newS*sizeof(T), _NORMAL_BLOCK,__FILE__,__LINE__); 
    s=newS; 
    return p!=NULL; 
} 

void T::Empty() 
{ 
    f=0; 
    return; 
} 

在文件TEntry.cpp:

T::T() 
{ 
} 

T::T(int i) 
{ 
    k=i; 
} 

void T::Relocate(int delta) 
{ 
    k+=delta; 
    return; 
} 
+0

調用類T是一個非常糟糕的選擇。請張貼您嘗試過的內容,很難說出您沒有展示時做錯了什麼。 – Mat 2013-02-24 08:00:05

+0

是否有任何不使用'std :: vector'的理由? – 2013-02-24 08:45:30

+0

請放心,我的實際班級並沒有被命名爲T.我現在有一個完整的工作對班,但是我只顯示了我的代碼的一小部分,剛夠問我的問題。 – Woody20 2013-02-24 17:47:52

回答

0

我想保持頭和實現文件分開

雖然可以做到這一點,這是一個有點一場噩夢。通常最好將模板的所有部分放在一起。

你可能需要的是這樣的:

template< typename TYPE > class T 
{ 
    // ... 
    TYPE* p; 
}; 

然後可以使用sizeof(TYPE)

你不能做的一件事,而且永遠不應該做的是將realloc與new和delete混合。 C++不支持用new和delete分配的內存的重新分配。相反,它具有容器,如std::vector可以爲您管理內存。

而且,如前所述,一個字母類和變量名稱不是一個好主意。 :)

+0

我將不得不檢查這種使用realloc。在Visual Studio中,'new'運算符使用malloc。 – Woody20 2013-02-24 17:53:14

+0

無論內部使用什麼或不使用內容。你不能安全地混合C(malloc/realloc/free)和C++(new/delete)內存分配策略。 – 2013-02-24 18:57:16

+0

什麼是不安全的混合他們?在這種情況下,可移植性不是問題。 – Woody20 2013-02-24 19:58:00

1

最簡單的方法是從一個完整的,工作的,非模板版本的T開始,它是根據您稍後要在模板中使用的一種類型編寫的(此處明顯選擇:TEntry) 。

一旦你有一個工作實現,你可以將其轉換爲模板。

  1. 爲模板參數選擇一個名稱。類型參數的通常名稱是T,但該名稱已在您的項目中使用,因此我將使用U
  2. 通過模板參數的名稱替換內TTEntry所有出現(U
  3. 模板頭部添加到T類定義:

    template <class U> 
    class T { 
        //... 
    
  4. 模板頭部添加到每個成員定義在類定義之外的T

    template <class U> 
    «return type» T<U>::«member specification» //... 
    
  5. En確保所有模板代碼都在頭文件中(直接或間接通過#include指令。模板不支持單獨編譯頭文件和源文件。
+0

謝謝你,這個評論是最有幫助的。我已經有了T和TEntry的工作實現。至於「單獨編譯」,這不是我想要的,只是單獨的文件。 #include的作用是將頭文件與實現文件結合起來。 – Woody20 2013-02-24 17:55:57

0

通常,最好將模板代碼保存在.h文件中。如果絕對必要,可以將實現放在.cpp文件中,詳情請諮詢C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis,Chaprer 6。

你可以去這樣的(削減不太重要的細節):

template <class T> 
class YourClass 
{ 
    YourClass() 
     : p(NULL), s(0), pG(NULL) 
    { 
     Empty(); 
    } 

    YourClass(G *pGIn, const unsigned long s, char nIn) 
    { 
     // ... implementation here 
    } 
    ~YourClass() 
    { 
     if(p!=NULL) 
      delete p; 
    } 


public: 
    bool Expand(const unsigned long newS) 
    { 
     T *pBefore=p; 
     p=(T *)_realloc_dbg(p, newS*sizeof(T), _NORMAL_BLOCK,__FILE__,__LINE__); 
     s=newS; 
     return p!=NULL; 
    } 


private: 
    G *pG; 
    char n; 
    unsigned long s; 
    int f; 
    T* p; 
}; 

幾點注意事項:

  • 命名你的類模板T真是一個糟糕的主意,因爲這是一個普遍的做法使用T作爲模板參數名稱。
  • 關於sizeof,在您的代碼示例中,它不適用於模板,而是適用於通常的類,無論如何,在類,類模板或模板參數上使用sizeof應該不會有任何問題。