2011-01-05 4 views
9

Mam następujący kod w pliku tylko nagłówka.Mieć globalną definicję funkcji w pliku nagłówkowym i uniknąć powielonego błędu powiązania symbolu

#pragma once 

class error_code { 
public: 
    unsigned __int64 hi; 
    unsigned __int64 lo;  
}; 

std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 

Dostaję błąd powiązania, gdy w projekcie jest 2 cpp uwzględnij ten plik nagłówkowy.

błąd LNK2005: "klasa kod_błędu operator __cdecl | (klasa kod_błędu const &, klasa ViTrox :: kod_błędu const &)" (? ?? U @@ YA AVerror_code @ 0 @ ABV10 @ 0 @ Z) już zdefiniowane w xxx.obj

wiem, że mogę rozwiązać ten problem, jeśli przeniosę definicję operator<< do pliku cpp, lub do pliku DLL.

Jednak chciałbym mieć je w pliku nagłówkowym SINGLE. Czy istnieje jakaś technika, aby to osiągnąć? Czy muszę oddzielić definicję od innego pliku?

+0

Komunikat o błędzie jest niezgodny z fragmentem kodu. –

Odpowiedz

16

Użyj słowa kluczowego inline.

inline std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
+0

Z ciekawości, czy wiesz, gdzie w specyfikacji mówi, że to działa? Używam tego jako hack na chwilę, ale nigdy nie widziałem przekonujących dowodów, że działa poprawnie. – templatetypedef

+1

Nie rozdział i werset, ale IIRC, jeśli nie masz "inline", który narusza ODR (a jeśli masz wbudowany, ale dwa lub więcej różnych organów, to również narusza ODR). –

+0

Kompilator musi widzieć treść funkcji wbudowanych i szablonów. W przeciwnym razie nie można ich wstawić ani utworzyć ich w momencie kompilowania oddzielnych jednostek tłumaczeniowych. – wilhelmtell

-1

Zdefiniuj tę funkcję w pliku .cpp (nie w pliku .h)

//yoursource.cpp 
#include "yourheader.h" 

std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
6

odbyć funkcję inline:

inline std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 

lub uczynić to funkcję szablonu:

template<class Ch, class Tr> 
std::basic_ostream<Ch,Tr>& operator<< (std::basic_ostream<Ch,Tr>& o, 
             const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
+0

dlaczego szablon działa również? czy szablony są wstawione? – Icebone1000

3

Możesz użyć tej funkcji ion static. Określa wewnętrzne powiązania, więc linker nie będzie dbał o to, czy funkcja jest już zdefiniowana w innych jednostkach tłumaczeniowych.

Lub, jak już wspomniano, można go ustawić jako inline. Nadal ma zewnętrzne powiązanie, ale standard pozwala zewnętrznym funkcjom wbudowanym mieć definicję w wielu jednostkach tłumaczeniowych.

Powiązane problemy