函数定义在类外时的链接器错误

时间:2014-09-18 11:14:13

标签: c++

我有文件::

//ClassA.h
#ifndef ClassA_H
#define ClassA_H

#pragma once
class ClassA
{
public:
void func1(){


}
ClassA(void) {

}
~ClassA (void) {


}

};

#endif

//ClassA1.h
#include "ClassA.h"

class ClassA1 {
    ClassA<2> b;
};


//ClassA1.cpp

#include "ClassA1.h"

//main_file.cpp
#include "ClassA1.h"
#include "iostream"
int main (int argc , char** argv) {

    std::cout<<"in main"<<std::endl;
}

所以这个编译得很好......一旦我在Class.h中的类外部定义类ClassA的函数,我就会在构建期间遇到以下错误

1>  LINK : c:\users\adudeja\documents\visual studio 2010\Projects\Test\Debug\Test.exe not found or not built by the last incremental link; performing full link
1>ClassA1.obj : error LNK2005: "public: void __thiscall ClassA::func1(void)" (?func1@ClassA@@QAEXXZ) already defined in main_file.obj
1>ClassA1.obj : error LNK2005: "public: __thiscall ClassA::ClassA(void)" (??0ClassA@@QAE@XZ) already defined in main_file.obj
1>ClassA1.obj : error LNK2005: "public: __thiscall ClassA::~ClassA(void)" (??1ClassA@@QAE@XZ) already defined in main_file.obj
1>c:\users\adudeja\documents\visual studio 2010\Projects\Test\Debug\Test.exe : fatal error LNK1169: one or more multiply defined symbols found

那么在类和类内部定义函数之间有什么区别。

以下是非工作代码......

#ifndef ClassA_H
#define ClassA_H

#pragma once
class ClassA
{
public:
void func1();
ClassA(void);
~ClassA(void);

};
void ClassA::func1(){


}
ClassA::ClassA(void) {

}
ClassA::~ClassA (void) {


}

#endif

2 个答案:

答案 0 :(得分:2)

  

那么在类和类内部定义函数之间有什么区别。

当你在类体中定义它时,它是隐式的inline,并且可以在多个文件中定义内联函数。

非内联函数必须只定义一次。

因此,要么将非内联定义放入单个.cpp文件中,而不是放在多个文件包含的标头中,要么使用inline关键字进行定义。

答案 1 :(得分:0)

好的,让我们看看......

在您的示例中,没有在类声明之外定义函数。

ClassA1.cpp和main_file.cpp&#34;参见&#34; ClassA的定义。由于内部定义的所有函数都被认为是inline,即链接器根本不会将其视为单独的函数,并且没有什么可抱怨的。

但如果你把例如在课堂声明之外的func1()(但仍在ClassA中),它不再被视为inline,它是一个独立的功能。但是因为它仍然可以被两个编译单元看到,所以它可以在两个翻译单元中编译。

因此,当您尝试将两个目标文件链接在一起时,您有两个func1()实例,并且链接器会抱怨。

解决方案是

  1. 在类声明中定义一个函数
  2. 一个单独翻译单元(ClassA.cpp)中定义该功能,并与之链接。
  3. 使用模板会稍微限制您的选项,因为模板代码必须对其使用的每个翻译单元可见,即您不能在标题中声明它并在其他地方实现它,只留下选项1.上面。


    后代码审核:

    ClassA.hpp:

    #ifndef ClassA_HPP
    #define ClassA_HPP
    
    class ClassA
    {
        public:
            ClassA();
            ~ClassA();
            void func1();
    };
    
    #endif
    

    ClassA.cpp:

    #include "ClassA.hpp"
    
    void ClassA::func1()
    {
        // ...
    }
    
    ClassA::ClassA()
    {
        // ...
    }
    
    ClassA::~ClassA()
    {
        // ...
    }
    

    ClassA1.hpp:

    #ifndef ClassA1_HPP
    #define ClassA1_HPP
    
    #include "ClassA.hpp"
    
    // Your example still assumed that ClassA is a template,
    // so I twisted that into an inheritance instead since
    // ClassA isn't a template anymore, and if it *were* a
    // template, it would change things significantly.
    
    // Perhaps trying too much at once?
    
    class ClassA1 : public ClassA
    {
        // ...
    };
    
    #endif
    

    ClassA1.cpp:

    #include "ClassA1.hpp"
    
    // ...
    

    main_file.cpp:

    #include "ClassA1.hpp"
    
    #include <iostream>
    
    int main( int argc, char * argv[] )
    {
        std::cout << "in main" << std::endl;
        return 0;
    }