大多数情况下,我“避免”在单个头文件中使用以下样式。
class a {
void fun();
};
void a::fun() {
}
为了避免以下错误。我尝试将cpp文件中的类定义与h文件中的类声明分开。例如,以下是错误的例子:
#include "b.h"
#include "a.h"
int main()
{
a aa;
b bb;
}
#ifndef A_H
#define A_H
#include <iostream>
class a {
public:
virtual int fun();
};
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
#ifndef B_H
#define B_H
#include <iostream>
#include "a.h"
class b {
public:
b();
};
#endif
#include "b.h"
#include "a.h"
b::b()
{
a aa;
aa.fun();
}
我会收到以下错误:
1>b.obj : error LNK2005: "public: virtual int __thiscall a::fun(void)" (?fun@a@@UAEHXZ) already defined in main.obj
然而,当来到模板时,我通常会这样做:
#ifndef A_H
#define A_H
#include <iostream>
template <typename T>
class a {
public:
virtual T fun();
};
template<typename T> T a<T>::fun()
{
T t;
std::cout << "a" << std::endl;
return t;
}
#endif
我知道这是一个好习惯吗?
感谢。
卓
答案 0 :(得分:2)
您可以通过将a::fun()
的定义声明为inline
来消除LNK2005错误。例如:
// a.h
// ...
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
使用模板时,问题不会发生,因为编译器/链接器负责确保每个模板实例化只有一个定义。
如果出于某种原因,您不希望该函数为inline
,那么您必须确保它只被编译一次。例如,像这样:
// a.h
// ...
#ifdef DEFINE_CLASS_A_FUNCTIONS
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
然后,在某个地方,你需要做这样的事情(恰好一次):
#define DEFINE_CLASS_A_FUNCTIONS
#include "a.h"
答案 1 :(得分:1)
1&gt; b.obj:错误LNK2005:“public: virtual int __thiscall a :: fun(void)“ (?fun @ a @@ UAEHXZ)已经定义了 main.obj
您收到此错误是因为a::fun()
不是inline
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
另外,请参阅C ++ FAQ:How can I avoid linker errors with my template functions?