C++ 在main中包含cpp文件时发生编译错误:内联函数与非内联函数
我有一个概念上的疑问,我将试着用一个例子来解释: main.cppC++ 在main中包含cpp文件时发生编译错误:内联函数与非内联函数,c++,compilation,linker,inline,redefinition,C++,Compilation,Linker,Inline,Redefinition,我有一个概念上的疑问,我将试着用一个例子来解释: main.cpp #include "array_list.cpp" int main() { array_list list1; return 0; } 场景1: 数组_list.cpp-> class array_list { private: int list[10]; public: array_list () {}; ~array_list () {}; void set_elemen
#include "array_list.cpp"
int main()
{
array_list list1;
return 0;
}
场景1:
数组_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;
}
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int i,int a) {
list[i] = a;
}
};
错误:
main.obj:错误LNK2005:“public:void _thiscall数组_列表::set_元素(int,int)”(?set_element@array_list@@QAEXHH@Z)已在数组_list.obj中定义
1> C:\Users\vrastog\Documents\Visual Studio 2012\Projects\C++learning\Debug\list using arrays.exe:致命错误LNK1169:找到一个或多个多重定义符号
情景2:
数组_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;
}
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”也应该在这里定义两次。我在这里遗漏了什么?类定义中使方法内联,因此不会在对象文件中导致多定义错误
inline
方法应该在使用它的每个翻译单元中实现,因此inline
方法编译成两个目标文件
C++标准草案(n3797)3.2.4:应在使用odr的每个翻译单元中定义内联函数
此外,3.2.6要求这些功能应完全相同
g++
使用弱符号实现此功能:内联函数是特殊的导出函数,在链接时不会导致多定义错误
在Linux下使用类似于nm
的工具,自己看看。它向对象文件中发出弱符号:
$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main
此外,如果不使用该函数,或编译器内联所有引用,则可能会对其进行优化。类定义中的方法会内联,因此不会在对象文件中导致多定义错误
inline
方法应该在使用它的每个翻译单元中实现,因此inline
方法编译成两个目标文件
C++标准草案(n3797)3.2.4:应在使用odr的每个翻译单元中定义内联函数
此外,3.2.6要求这些功能应完全相同
g++
使用弱符号实现此功能:内联函数是特殊的导出函数,在链接时不会导致多定义错误
在Linux下使用类似于nm
的工具,自己看看。它向对象文件中发出弱符号:
$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main
此外,如果不使用该函数,或编译器内联所有引用,它可能会得到优化。请不要包含
.cpp
文件
在第一个示例中,函数是在类外定义的,您需要添加内联
,否则它是一个多定义
在第二个示例中,函数是在类定义中定义的,因此它是一个隐式内联函数(就像编译器为您添加了
内联
),这就是为什么它不会导致多个定义。请不要包含.cpp
文件
在第一个示例中,函数是在类外定义的,您需要添加内联
,否则它是一个多定义
在第二个示例中,函数是在类定义中定义的,因此它是一个隐式内联函数(就像编译器为您添加了
内联
),这就是为什么它不会导致多个定义。为什么您要包含.cpp
文件?!?这些不是要包含在内的,而是单独编译并最终链接起来的。我知道这不应该作为一个好的编码实践包含在内。但理论上这是可能的。我想通过这个例子来理解潜在的编译问题。这个问题的可能重复本质上是问为什么内联函数可以被定义多次。@Drew:完全是的!!你到底为什么要包括一个.cpp
文件?!?这些不是要包含在内的,而是单独编译并最终链接起来的。我知道这不应该作为一个好的编码实践包含在内。但理论上这是可能的。我想通过这个例子来理解潜在的编译问题。这个问题的可能重复本质上是问为什么内联函数可以被定义多次。@Drew:完全是的!!你的意思是它不在main.obj或array_list.obj或两者中?如果它没有进入任何obj文件,那么内联方法在哪里编译?@user267096我已经扩展(并更正)了答案,包含了你问题的答案。谢谢你的回答。基本上消除了我的疑虑。作为一个扩展,内联函数在使用它的每个转换单元中都应该有定义的原因是什么?@tyl3rdurd3n如果您看到函数的定义,您可以进行内联。如果在翻译单元中看不到函数的定义,编译器所能做的就是生成一个函数调用。你的意思是它不在main.obj或array_list.obj或两者中?如果它没有进入任何obj文件,那么内联方法在哪里编译?@user267096我已经扩展(并更正)了答案,包含了你问题的答案。谢谢你的回答。基本上消除了我的疑虑。作为一个扩展,内联函数在使用它的每个转换单元中都应该有定义的原因是什么?@tyl3rdurd3n如果您看到函数的定义,您可以进行内联。如果在翻译单元中看不到函数的定义,编译器所能做的就是生成函数调用。