在main中包含cpp文件时的编译错误:内联函数与非内联函数

时间:2014-06-24 10:35:39

标签: c++ compilation linker inline redefinition

我有一个概念上的怀疑,我试图用一个例子来表达:

的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'应该在这里定义两次。我在这里缺少什么?

2 个答案:

答案 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 ;为什么它不会造成多重定义。