我有一个概念上的怀疑,我试图用一个例子来表达:
的main.cpp
#include "array_list.cpp"
int main()
{
array_list list1;
return 0;
}
Scenario1: array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int,int);
};
void array_list::set_element (int i,int a) {
list[i] = a;
}
错误:
main.obj:错误LNK2005:" public:void __thiscall array_list :: set_element(int,int)" (?set_element @ array_list @@ QAEXHH @ Z)已在array_list.obj中定义 1> C:\ Users \ vrastog \ Documents \ Visual Studio 2012 \ Projects \ C ++ learning \ Debug \ list using arrays.exe:致命错误LNK1169:找到一个或多个多重定义的符号
场景2: array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int i,int a) {
list[i] = a;
}
};
错误:没有错误!!
问题:我理解错误的原因。已经定义了两次相同的方法,一次在main.obj中,第二次在array_list.obj中,因此,它应该是一个错误。 我的问题是为什么第二种情况有效?在这里,因为我们在主文件中包含了array_list.cpp,所以' set_element'应该在这里定义两次。我在这里缺少什么?
答案 0 :(得分:2)
类内定义使方法内联,因此不会在目标文件中导致多重定义错误。
inline
方法应该在其使用的每个翻译单元中实现,因此inline
方法会编译成两个目标文件。
C ++标准草案(n3797)3.2.4 :内联函数应在每个使用它的翻译单元中定义。
同样 3.2.6 要求这些功能完全相同。
g++
使用弱符号实现这一点:内联函数是特殊的导出函数,在链接时不会导致多个定义错误。
在Linux下使用nm
之类的工具,亲眼看看。它在目标文件中发出一个弱符号:
$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main
此外,如果您不使用该函数,或者编译器内联所有实例,它可能会被优化。
答案 1 :(得分:2)
请不要包含.cpp
个文件。
在第一个示例中,函数是在课外定义的,您需要添加inline
,否则它是一个多重定义。
在第二个例子中,函数在类定义中定义,因此它是一个隐式内联函数(就像编译器为你添加了inline
一样),&#39 ;为什么它不会造成多重定义。