多文件中定义函数:重编译问题

来源:互联网 发布:淘宝优惠券领取app 编辑:程序博客网 时间:2024/06/05 23:02

今天在练习 非友元式运算符重载的时候出现了一个问题(using 什么的省略)

//A.h

class A{

public:

  void fun();

}

//A.cpp

#include "A.h"

void A::fun(){

}

ostream &operator<<(ostream &out, A &x){

 out<<"test";

 return out;

}

//main.cpp

#include "A.h"

int main(){

 A a;

 cout<<a;

 return 0;

}


    错误提示没有A类型的<<重载, 这是因为main中的<<根本没有重载成功。

    

    为什么没有重载成功?因为我们包含A.h的时候,根本没有把A.cpp中的类容包含进来。

    

    但是我们却可以成功使用a.fun(),为什么呢,A.cpp中的类容不是没有包含进来吗?

    

    这是因为域作用符::发挥了作用,当编译器编译A.cpp的时候,把A.h中的声明和它的实现连接到了一起,虽然我们没有包含A.cpp,但是A.h中的类已经和它的实现连在一起包含了。但是operator<<就没这么幸运了,他可没人领到main中去。

  

     那么我们会想,我把operator<<放到A.h中不就行了?

     是的,虽然operator<<这时候被main.cpp包含了,但是同时,由于A.cpp中的#include "A.h",使operator<<既在main.cpp中定义又在A.cpp中定义,这样重复定义会出错。

 

    当一个源码中有太多函数时,我们希望用几个源码来分别存放这些函数,那么会有多个CPP文件进行编译,这时很可能出现重复编译的问题。

例子1

//文件A A.h

#ifndef A_H

#define A_H

#include <iostream>

using namespace std;

class F{

};

fun(){

   cout<<'A';

}

#endif

 

//文件B B.cpp

//文件C C.cpp

#include "A.h"

int main(){

 fun();

 return 0;

}

这时候 fun()函数正常运行,因为我们在C文件中用到fun()在A.h中定义过,符合要求。(注意,此时B文件是空的。)

下面,因为我们在头文件中声明了F类,自然要新建一个CPP定义F,那么需要在B中包含A

//文件B B.cpp

#include "A.h"

我们暂时不定义具体类容,此时再编译,出现错误:

错误1error LNK2005: "void __cdecl fun(void)" (?fun@@YAXXZ) 已经在 B.obj 中定义


这是因为,虽然我们在C中只包含了一个头文件,看似只定义了一次fun(),但是编译器还要编译另一个CPP,B,而B中因为包含了A,所以B再次定义了fun(),这样fun定义了两次,编译器就会罢工。

解决办法有两个:

1)将fun的定义放在文件C中

2)A.h中只声明fun,将fun的定义放到B中

 

总结:声明可以重复,但定义不可以,头文件中尽量只声明,不要具体实现。

原创粉丝点击