链接C ++模板中的错误

时间:2012-04-24 15:30:57

标签: c++ templates linker

我需要生成一个简单的Logger(带有第三方库),需要链接到dll。因此我生成了一个类,其中一些类方法是模板,代码编译正常,但我得到链接器错误。我正在使用MS VS 2008和gcc-4进行编译。代码是:

Log.h类:

class MiniLogger
{
private:
   std::ofstream mOutPutFile;
protected:
   void write (std::string const& text);
public:
   ~MiniLogger();
   MiniLogger( std::string const& lName) throw(FileError);
   static MiniLogger* getInstance(std::string const & fName);
   static void destoryInstance(MiniLogger*);

  template<class T>
  MiniLogger& operator<<(T & data);
  MiniLogger& operator<<(std::ostream& (*func)(std::ostream&) );

};


MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{

   //mOutPutFile << out;
   return *this;
}
template<class T>
MiniLogger& MiniLogger::operator<< (T  & data)
{
 //Just try with out calling other method
// write(data);
   return *this;
}

在main中,我实例化了Object并使用它:

#include "log.h"

int main()
{


    MiniLogger &a=*(MiniLogger::getInstance("text.txt"));

    a << "text" << std::endl;


return 0;
}

我得到了

@ubu11-10-64b-01:~/cplus/template$ g++ main.cpp log.cpp
/tmp/cccMdSBI.o: In function `MiniLogger::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))':
log.cpp:(.text+0x0): multiple definition of `MiniLogger::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
/tmp/ccj3dfhR.o:main.cpp:(.text+0x0): first defined here

1 个答案:

答案 0 :(得分:4)

您已在头文件中定义了一个函数。由于该头文件包含在多个转换单元中(即main.cpp和log.cpp),因此您已经多次定义了该函数。 (参见One Definition Rule。)

声明函数inline并在头文件中定义它,或在头文件中声明它extern并在一个源文件中定义。

有问题的功能是:MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))

解决方案#1:

// Log.h
inline
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{
 //mOutPutFile << out;
 return *this;
}

解决方案#2:

// Log.h
extern
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&));

// Log.cpp
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{
 //mOutPutFile << out;
 return *this;

}

<小时/> 旁注:意识到头文件template<class T> MiniLogger& MiniLogger::operator<< (T & data)中的下一个实体不是函数 - 它是一个函数模板 - 并且不同的建议适用于它。根据经验,在头文件中定义函数模板,但不应定义头文件中的函数。 (这个经验法则有例外。)