Ada*_*yos 44 c++ definition friend
我在几年前参加了一个入门课程后试图重新学习C++,而且我遇到了一些基本的问题.尝试使用友元功能时出现我当前的问题.这是我的2个文件中的代码.
第一:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
第二:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是"funct()'的多重定义".在将其声明为友元函数时,我使用了错误的语法吗?
Moh*_*ugh 60
这是一个高度简化但希望相关的视图,说明在C++中构建代码时会发生什么.
C++在以下不同阶段分割生成机器可执行代码的负载 -
预处理 - 这是#define您可能正在使用的任何宏等扩展的地方.
编译 - 每个cpp文件以及该#include文件中的所有d文件直接或间接(一起称为编译单元)被转换为机器可读对象代码.
这是C++还检查所有定义的函数(即包含{ }例如
正文以void Foo( int x){ return Boo(x); })有效方式引用其他函数)的地方.
它的方式是坚持你在void Boo(int);调用它之前至少提供这些其他函数的声明(例如),这样它就可以检查你是否正确地调用了它.这可以直接在调用它的cpp文件中完成,也可以通常在包含的头文件中完成.
请注意,只有与此cpp和包含文件中定义的函数对应的机器代码才会构建为此编译单元的对象(二进制)版本(例如Foo),而不是仅仅声明的那些(例如Boo).
链接 - 这是C++寻找在每个编译单元中声明和调用的东西并将其链接到被调用的地方的阶段.现在,如果找不到此函数的定义,则链接器会放弃并输出错误.类似地,如果它找到相同函数签名的多个定义(基本上是它所采用的名称和参数类型),它也会因为它认为它不明确并且不想任意选择一个而出错.
后者就是你的情况.通过做#include了的fun.cpp文件,都fun.cpp和mainfile.cpp有一个定义funct()和链接器不知道在你的程序中使用哪一个和抱怨它.
上面提到的Vaughn的修复是不包含带有funct()in 的定义的cpp文件,mainfile.cpp而是funct()在单独的头文件中移动声明并将其包括在中mainline.cpp.通过这种方式,编译器将获得使用的声明,funct()并且链接器将只获得funct()from的一个定义,fun.cpp并将自信地使用它.
Vau*_*ato 26
问题是如果你在程序的两个地方包含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;
}
};
Run Code Online (Sandbox Code Playgroud)
fun.cpp:
#include "fun.hpp"
using namespace std;
void funct(){
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
Run Code Online (Sandbox Code Playgroud)
mainfile.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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,通常建议避免using namespace std在头文件中使用.
| 归档时间: |
|
| 查看次数: |
113518 次 |
| 最近记录: |