函数有多个定义时出错 几年前我尝试重新学习C++,我遇到了一些基本问题。我当前的问题发生在尝试使用friend函数时。这是我在2个文件中的代码
第一:函数有多个定义时出错 几年前我尝试重新学习C++,我遇到了一些基本问题。我当前的问题发生在尝试使用friend函数时。这是我在2个文件中的代码,c++,definition,friend,C++,Definition,Friend,第一: // 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(){
// 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;
}
//fun.cpp
#包括
使用名称空间std;
甲级{
friend-void函数();
公众:
classA(inta=1,intb=2):propa(a),propb(b){cout问题是,如果在程序中的两个位置包含fun.cpp,那么最终将定义它两次,这是无效的
您不想包括cpp
文件。您想包括头文件
头文件应该只有类定义。您将单独编译的相应cpp
文件将有函数定义
fun.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;
}
};
#包括
甲级{
friend-void函数();
公众:
CyrA(int A=1,int B=2):PROPA(A),PROB(B){STD::CUT这里是一个高度简化但希望相关的视图,当您在C++中构建代码时发生了什么。
C++将生成机器可执行代码的负载分为以下不同阶段-
预处理-这是您可能正在使用的任何宏
#定义
s等的扩展位置
#include
d文件被转换为机器可读的目标代码
<>这是C++还检查所有函数定义的(即包含在代码< > {<代码/代码>代码> } /代码>的正文。
void Foo(int x){return Boo(x);})
正在以有效的方式引用其他函数
这样做的方式是,在调用它之前,坚持至少提供这些其他函数的声明(例如,void Boo(int);
),以便它可以检查您是否正确调用了它。这可以直接在调用它的cpp文件中完成,也可以通常在包含的头文件中完成
请注意,只有与此cpp中定义的函数和包含的文件相对应的机器代码才会构建为此编译单元的对象(二进制)版本(例如Foo),而不是仅声明的机器代码(例如Boo)fun.cpp
文件执行#include
,fun.cpp
和main.cpp
都有funct()
的定义,链接器不知道在您的程序中使用哪一个,并且正在抱怨
Vaughn提到的修复方法是在
mainfile.cpp
中不包含定义为funct()
的cpp文件,而是将funct()
的声明移动到单独的头文件中,并将其包含在mainline.cpp
中。这样编译器将获得funct()的声明<代码> >链接器将得到一个定义:<代码>函数()/>代码> <代码>乐趣.CPP < /代码>,并将它带到信心。 < p>这个问题发生是因为您调用了“代码>乐趣.CPP < /C>”而不是<代码>乐趣.HPP。因此C++编译器发现函数.CPP定义两次,并引发此错误。
将main.cpp
文件的第3行从#包含“fun.cpp”
更改为#包含“fun.hpp”
您有#包含“fun.cpp”
在main文件.cpp
中,因此编译时使用:
g++-o hw1 mainfile.cpp
但是,如果将这些链接在一起进行编译,则
g++-g-std=c++11-Wall-pedantic-c-o-fun.o-fun.cpp
g++-g-std=c++11-Wall-pedantic-c-o mainfile.o mainfile.cpp
正如上面提到的,添加#包括“fun.hpp”
将需要完成,否则将无法工作。但是,您使用func()
函数的情况与我的问题略有不同
我在执行HW分配和由较低的bash配方编译的自动加载器时遇到了这个问题,但在本地,它使用较高的bash工作。它还可以帮助一些链接器包装标题保护——继续搜索#ifndef@CarlNorum我的印象是,多个定义错误是链接器错误,而不是编译错误。但也许我是错了。是的,但标题保护与此无关。除非你在标题中做了一些疯狂的事情,那就是。为什么它适用于类而不是函数?我看不出与要求将其放置在cpp文件中的类定义相比,函数有什么特殊之处。@ElefEnt:类纯粹是编译时的实体。如果定义了一个从未使用过的类,则编译器不会创建任何机器代码。但是,非内联函数定义意味着实际创建机器代码,无论您是否使用它。您只希望该机器代码存储在一个对象文件中。如果要将函数定义放在头中,则d意味着在包含标题的任何位置创建机器代码。
#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;
}
};
#include "fun.hpp"
using namespace std;
void funct(){
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
#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;
}