C++ 函数的多个定义错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17904643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Error with multiple definitions of function
提问by Adad Dayos
I am trying to relearn C++ after taking an intro course a few years ago and I'm having some basic problems. My current problem occurs when trying to use a friend function. Here is my code in 2 files.
几年前参加了介绍课程后,我正在尝试重新学习 C++,但我遇到了一些基本问题。我当前的问题发生在尝试使用友元函数时。这是我在 2 个文件中的代码。
First:
第一的:
// fun.cpp
#include <iostream>
using namespace std;
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
cout<<"propa="<<propa<<endl<<"propb="<<propb<<endl;
}
};
void funct(){ // ERROR HERE
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
Second:
第二:
// mainfile.cpp
#include <iostream>
#include "fun.cpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
The error I am getting is "multiple definition of `funct()'". Am I using the wrong syntax when declaring it as a friend function?
我得到的错误是“‘funct()’的多重定义”。将其声明为友元函数时,我是否使用了错误的语法?
回答by Mohit Chugh
Here is a highly simplified but hopefully relevant view of what happens when you build your code in C++.
这是一个高度简化但希望相关的视图,说明在使用 C++ 构建代码时会发生什么。
C++ splits the load of generating machine executable code in following different phases -
C++ 将生成机器可执行代码的负载分为以下不同阶段 -
Preprocessing- This is where any macros -
#define
s etc you might be using get expanded.Compiling- Each cpp file along with all the
#include
d files in that file directly or indirectly (together called a compilation unit) is converted into machine readable object code.This is where C++ also checks that all functions defined (i.e. containing a body in
{
}
e.g.void Foo( int x){ return Boo(x); })
are referring to other functions in a valid manner.The way it does that is by insisting that you provide at least a declaration of these other functions (e.g.
void Boo(int);
) before you call it so it can check that you are calling it properly among other things. This can be done either directly in the cpp file where it is called or usually in an included header file.Note that only the machine code that corresponds to functions defined in this cpp and included files gets built as the object (binary) version of this compilation unit (e.g. Foo) and not the ones that are merely declared (e.g. Boo).
Linking- This is the stage where C++ goes hunting for stuff declared and called in each compilation unit and links it to the places where it is getting called. Now if there was no definition found of this function the linker gives up and errors out. Similarly if it finds multiple definitions of the same function signature (essentially the name and parameter types it takes) it also errors out as it considers it ambiguous and doesn't want to pick one arbitrarily.
预处理- 这是
#define
您可能使用的任何宏 - s 等得到扩展的地方。编译- 每个 cpp 文件以及该
#include
文件中的所有d 文件直接或间接(统称为编译单元)被转换为机器可读的目标代码。这是 C++ 还检查所有定义的函数(即包含在
{
}
eg 中的主体)以void Foo( int x){ return Boo(x); })
有效方式引用其他函数的地方。它这样做的方式是坚持
void Boo(int);
在调用之前至少提供这些其他函数的声明(例如),以便它可以检查您是否正确调用了它。这可以直接在调用它的 cpp 文件中完成,也可以通常在包含的头文件中完成。请注意,只有与此 cpp 中定义的函数和包含文件相对应的机器代码才能构建为该编译单元的对象(二进制)版本(例如 Foo),而不是仅声明的机器代码(例如 Boo)。
链接- 这是 C++ 寻找在每个编译单元中声明和调用的东西并将其链接到它被调用的地方的阶段。现在如果没有找到这个函数的定义,链接器就会放弃并出错。类似地,如果它发现同一函数签名的多个定义(本质上是它采用的名称和参数类型),它也会出错,因为它认为它不明确并且不想任意选择一个。
The latter is what is happening in your case. By doing a #include
of the fun.cpp
file, both fun.cpp
and mainfile.cpp
have a definition of funct()
and the linker doesn't know which one to use in your program and is complaining about it.
后者就是你的情况。通过做#include
了的fun.cpp
文件,都fun.cpp
和mainfile.cpp
有一个定义funct()
和链接器不知道在你的程序中使用哪一个和抱怨它。
The fix as Vaughn mentioned above is to not include the cpp file with the definition of funct()
in mainfile.cpp
and instead move the declaration of funct()
in a separate header file and include that in mainline.cpp
. This way the compiler will get the declaration of funct()
to work with and the linker would get just one definition of funct()
from fun.cpp
and will use it with confidence.
Vaughn 上面提到的修复是不包含具有funct()
in定义的 cpp 文件,mainfile.cpp
而是将 的声明移动到funct()
单独的头文件中并将其包含在mainline.cpp
. 通过这种方式,编译器将获得要使用的声明,funct()
而链接器将仅获得funct()
from 的一个定义,fun.cpp
并可以放心地使用它。
回答by Vaughn Cato
The problem is that if you include fun.cpp in two places in your program, you will end up defining it twice, which isn't valid.
问题是如果你在程序的两个地方包含 fun.cpp,你最终会定义它两次,这是无效的。
You don't want to include cpp
files. You want to include header files.
您不想包含cpp
文件。您想包含头文件。
The header file should just have the class definition. The corresponding cpp
file, which you will compile separately, will have the function definition.
头文件应该只有类定义。cpp
您将单独编译的相应文件将具有函数定义。
fun.hpp:
有趣的.hpp:
#include <iostream>
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){std::cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
std::cout<<"propa="<<propa<<endl<<"propb="<<propb<< std::endl;
}
};
fun.cpp:
乐趣.cpp:
#include "fun.hpp"
using namespace std;
void funct(){
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
mainfile.cpp:
主文件.cpp:
#include <iostream>
#include "fun.hpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
Note that it is generally recommended to avoid using namespace std
in header files.
请注意,通常建议避免using namespace std
在头文件中使用。