c++ 中类重复定义的分析与解决办法

在C++中将类以及类中的成员函数的声明放在.h的头文件中,而将类中成员函数的定义(即实现代码)放在.cpp的源文件中,这样我们的程序设计起来更加的模块化,但是,这样的设计也会带来一些问题,我们分析以下的代码,从中找的问题,并给出问题的解决方法。首先我们在VC下新建一个工程(工程名自己随便命名),然后在此工程下新建两个.h的头文件(文件名分别为Animal.h和 Fish.h),继续新建三个.cpp的源文件(文件名分别是Animal.cpp、Fish.cpp、Main.cpp),完成后分别将以下的代码copy到相应的文件下。

如下图所示:


Animal.h

[cpp]  view plain  copy
  1. class Animal  
  2. {  
  3. public :  
  4.            Animal(int height, int weight) ;  
  5.            void eat() ;  
  6.            void sleep() ;  
  7.            virtual void breathe() ;  
  8. } ;  

Fish.h

[cpp]  view plain  copy
  1. #include"Animal.h"  
  2.    
  3. class Fish :public Animal  
  4. {  
  5. public :  
  6.       Fish() ;  
  7.       void breathe() ;  
  8. } ;  

Animal.cpp

[cpp]  view plain  copy
  1. #include<iostream.h>  
  2. #include"Animal.h"  
  3.    
  4. Animal::Animal(intheight, int weight)  
  5. {  
  6.    
  7. }  
  8.    
  9. voidAnimal::eat()  
  10. {  
  11.       cout << "Animal eat"<< endl ;  
  12. }  
  13. voidAnimal::sleep()  
  14. {  
  15.       cout << "Animal sleep"<< endl ;  
  16. }  
  17. void Animal::breathe()  
  18. {  
  19.       cout << "Animal breathe"<< endl ;  
  20. }  

Fish.cpp

[cpp]  view plain  copy
  1. #include<iostream.h>  
  2. #include"Fish.h"  
  3. Fish::Fish() :Animal(300, 400)  
  4. {}  
  5. voidFish::breathe()  
  6. {  
  7.       cout << "fish breathe"<< endl ;  
  8. }  

Main.cpp

[cpp]  view plain  copy
  1. #include<iostream.h>  
  2. #include"Animal.h"  
  3. #include"Fish.h"  
  4.    
  5. void fun(Animal*pAn)  
  6. {  
  7.       pAn->breathe() ;  
  8. }  
  9.    
  10. void main()  
  11. {  
  12.       Fish fh ;  
  13.       Animal *pAn ;  
  14.       pAn = &fh ;  
  15.       fun(pAn) ;  
  16. }  

完成后,点击编译后,会发现VC编译器报错,具体如下:


大概意思就是Animal类重复定义。

我们来分析一下源代码。

首先是执行Main.cpp源文件中的代码,发现#include "Animal.h"此句代码,编译器回去查找Animal.h头文件,发现Animal这个类已经定义,继续执行,执行到#include "Fish.h"这句代码时,编译器便会去查找Fish.h头文件,在Fish.h头文件中,编译器执行到#include "Animal.h"时,便又去查找Animal.h头文件中的代码,再次发现类Animal的定义,这样,编译器感觉类Animal重复定义了两次,于是,编译器便会报错。

那么,我们该怎样去解决这种问题呢?

方法一:

既然我们已经分析了出现这种问题的原因,那么,我们可以发现在Main.cpp文件中,我们引用了#include "Animal.h"头文件,而当我们再次去引用#include "Fish.h"头文件时,发现在Fish.h文件中也引用了#include "Animal.h"头文件,既然这样,我们何不在Main.cpp文件中将#include "Animal.h"注释掉,这样就避免了重复定义的问题了,其实这样做也是可以的,但是,我们想想,如果我们在写一个大型的程序时,往往有几十个甚至成百上千个的类,其中的继承关系又是那么的复杂的时候,我们便会很难分析到那块可以不写(注释掉),所以,这种方法不适合大型程序的设计。于是,我们又想出了下面的方法:


方法二:

看如下的代码(保持.cpp文件不变,我们在.h头文件上解决该问题)

Animal.h

[cpp]  view plain  copy
  1. #ifndefANIMAL_H_H  
  2. #defineANIMAL_H_H  
  3. class Animal  
  4. {  
  5. public :  
  6.            Animal(int height, int weight) ;  
  7.            void eat() ;  
  8.            void sleep() ;  
  9.            virtual void breathe() ;  
  10. } ;  
  11.    
  12. #endif  

Fish.h

[cpp]  view plain  copy
  1. #include"Animal.h"  
  2.    
  3. #ifndef FISH_H_H  
  4. #define FISH_H_H  
  5. class Fish :public Animal  
  6. {  
  7. public :  
  8.       Fish() ;  
  9.       void breathe() ;  
  10. } ;  
  11. #endif  

观察改写后的代码,发现我们在类的定义前后分别加上了#ifndef…#define…#endif语句,哪么这条语句有什么作用呢?还是刚才的分析过程,当编译器去执行Main.cpp源文件中的代码,发现#include "Animal.h"此句代码,编译器回去查找Animal.h头文件,执行到#ifndef ANIMAL_H_H时,编译器会做出如下的判断,若ANIMAL_H_H没有被定义,便定义它(#define ANIMAL_H_H被执行)继续执行,执行到#include "Fish.h"这句代码时,编译器便会去查找Fish.h头文件,在Fish.h头文件中,编译器执行到#include "Animal.h"时,便又去查找Animal.h头文件中的代码,与上面的一样,编译器会判断ANIMAL_H_H定义了没有,若没有,便进行定义,反之,将跳过#ifndef…#endif间的代码,继续向后执行,知道程序执行完毕。

现在再次编译一下更改后的代码,发现程序并没有报错,执行后输出如下:



上面的使用#ifdef…#endif解决重复定义的问题在MFC编程中会经常的看到,所以,希望学习MFC编程的编程爱好者能够好好的阅读和分析一下,亲自做做实验,有利于个人理解。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值