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

linker error when function definition is outside class

本文关键字:链接 错误 定义 函数      更新时间:2023-10-16

我有文件::

//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:usersadudejadocumentsvisual studio 2010ProjectsTestDebugTest.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:usersadudejadocumentsvisual studio 2010ProjectsTestDebugTest.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

那么,在类外定义函数和在类内定义函数有什么区别呢。

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

非内联函数只能定义一次。

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

好的,让我们看看。。。

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

ClassA1.cpp和main_file.cpp都"参见"ClassA的定义。由于类声明中定义的所有函数都被视为inline,即链接器根本不将其视为一个单独的函数,也没有什么可抱怨的。

但是,如果你把func1()的定义放在类声明之外(但仍然在ClassA中),它就不再被认为是inline,它是一个单独的函数。但由于它仍然对两个编译单元可见,因此它在两个翻译单元中都进行了编译。

因此,当您尝试将两个对象文件链接在一起时,您得到了func1()的两个实例,链接器会抱怨。

解决方案是任一

  1. 在类声明中定义一个函数,
  2. 一个独立的翻译单元(ClassA.cpp)中定义函数,并与之链接

使用模板在一定程度上限制了您的选择,因为模板代码必须对使用它的每个翻译单元可见,即您不能只在标头中声明它并在其他地方实现它,只剩下选项1。在上面


邮编审核:

A类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()
{
    // ...
}

类别1: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;
}