2011-03-27 50 views
12

今天我的第三個問題;-),但我真的很新的c + +模板編程和運算符重載。C++模板專門化 - 鏈接器錯誤多個定義

我嘗試以下操作:

terminallog.hh

//snipped code 

class Terminallog { 
public: 

    Terminallog(); 
    Terminallog(int); 
    virtual ~Terminallog(); 

    template <class T> 
    Terminallog & operator<<(const T &v); 
    template <class T> 
    Terminallog & operator<<(const std::vector<T> &v); 
    template <class T> 
    Terminallog & operator<<(const T v[]); 
    Terminallog & operator<<(const char v[]); 

//snipped code 
}; 

//snipped code 
template <class T> 
Terminallog &Terminallog::operator<<(const T &v) { 
    std::cout << std::endl; 
    this->indent(); 
    std::cout << v; 
    return *this; 
} 

template <class T> 
Terminallog &Terminallog::operator<<(const std::vector<T> &v) { 
    for (unsigned int i = 0; i < v.size(); i++) { 
     std::cout << std::endl; 
     this->indent(); 
     std::cout << "Element " << i << ": " << v.at(i); 
    } 
    return *this; 
} 

template <class T> 
Terminallog &Terminallog::operator<<(const T v[]) { 
    unsigned int elements = sizeof (v)/sizeof (v[0]); 
    for (unsigned int i = 0; i < elements; i++) { 
     std::cout << std::endl; 
     this->indent(); 
     std::cout << "Element " << i << ": " << v[i]; 
    } 
    return *this; 
} 

Terminallog &Terminallog::operator<<(const char v[]) { 
    std::cout << std::endl; 
    this->indent(); 
    std::cout << v; 
    return *this; 
} 
//snipped code 

試圖編譯這段代碼,它給了我一個鏈接錯誤:

g++ src/terminallog.cc inc/terminallog.hh testmain.cpp -o test -Wall -Werror 
/tmp/ccifyOpr.o: In function `Terminallog::operator<<(char const*)': 
testmain.cpp:(.text+0x0): multiple definition of `Terminallog::operator<<(char const*)' 
/tmp/cccnEZlA.o:terminallog.cc:(.text+0x0): first defined here 
collect2: ld returned 1 exit status 

Therfore我目前我撞頭靠在牆上,尋找解決方案。但我不能找到一個在牆上...

這將是巨大的,如果有人能告訴我我的錯誤

謝謝你這麼多

ftiaronsem

回答

13

此功能

Terminallog &Terminallog::operator<<(const char v[]) { 
    std::cout << std::endl; 
    this->indent(); 
    std::cout << v; 
    return *this; 
} 

不是模板,而是常規的成員函數。如果這個.h文件包含在幾個.cpp文件中,它會導致你看到的多重定義錯誤。如果你聲明它爲inline,編譯器將允許多個定義,並且你的錯誤應該被修復。

inline 
Terminallog &Terminallog::operator<<(const char v[]) { 
+0

哇,完全正確。非常感謝。但我仍然有一個問題:我在頭文件中有一個包含守護進程。因此它應該只包含一次。然而,爲什麼我得到這個錯誤呢? – ftiaronsem 2011-03-28 00:13:44

+0

@fitaronsem:包括警衛在一個單獨的TU中只有多個定義_only_。你的錯誤是_link_錯誤,而不是編譯錯誤;當你在多個TU中有多個定義時,包括警衛在內無法提供幫助。因此,作爲一般規則,不要將非內聯或非模板函數或變量定義放在標題中。 – 2011-03-28 00:15:47

+0

在編譯* .cpp文件的過程中,包含防止多次包含它,從而防止多次定義類的*編譯器錯誤*。但是,您看到的問題不是編譯器錯誤,而是*鏈接器錯誤*。也就是說,當你的多個.cpp文件加入到最終的可執行文件或庫文件時。因此你需要告訴鏈接器可以接受這個函數的多個*相同的*拷貝,並且'inline'服務於這個目的。 – Pablo 2011-03-28 00:18:22