C++:重定义:class类型重定义

概述

    在C++中将类以及类中的成员函数的声明放在.h头文件中,而将类中成员函数的定义(函数的实现)放在.cpp源码中,这样我们的程序设计起来会更加模块化,但是,这样会带来一些问题:比如类型重定义等。

1:我们建一个工程(建立两个头文件Animal.h和Fish.h,三个.cpp源文件:Animal.cpp,Fish.cpp,Main.cpp)

Animal.h

class Animal
{
public:
	Animal(int height,int weight);
	void eat();
	void sleep();
	virtual void breathe();
};
Fish.h

#include "Animal.h"

class Fish:public Animal
{
public:
	Fish();
	void breathe();

private:

};
Fish.cpp

#include<iostream>
#include"Fish.h"
using namespace std;
Fish::Fish() :Animal(300, 400)
{}
void Fish::breathe()
{
    cout << "fish breathe" << endl;
}
Animal.cpp

#include<iostream>
#include"Animal.h"
using namespace std;

Animal::Animal(int height, int weight)
{

}

void Animal::eat()
{
    cout << "Animal eat" << endl;
}
void Animal::sleep()
{
    cout << "Animal sleep" << endl;
}
void Animal::breathe()
{
    cout << "Animal breathe" << endl;
}
Main.cpp

#include "Animal.h"
#include "Fish.h"


using namespace std;

void fun(Animal* pAn)
{
    pAn->breathe();
}


int main(){
    Fish fh;
    Animal* pAn;
    pAn = &fh;
    fun(pAn);
}

2: 上述代码运行会报如下错误:

Animal : "class" 类型重定义 

3:分析下源码,为啥会报 Animal类重复定义 

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

4:如何解决类 Animal重复定义的问题

分析程序手动删除 多余include 引入的  Animal类定义

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

4.1 :在头文件中增加 #ifndef .... #define ....#ednif

Animal.h

#ifndefANIMAL_H_H
#defineANIMAL_H_H
class Animal
{
public :
           Animal(int height, int weight) ;
           void eat() ;
           void sleep() ;
           virtual void breathe() ;
} ;
 
#endif
Fish.h

#include"Animal.h"
 
#ifndef FISH_H_H
#define FISH_H_H
class Fish :public Animal
{
public :
      Fish() ;
      void breathe() ;
} ;
#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头文件中的代码,
  • 与上面的一样,执行到#ifndef ANIMAL_H_H时,编译器会判断ANIMAL_H_H定义了没有,若没有,便进行定义,反之,将跳过#ifndef…#endif间的代码,继续向后执行,知道程序执行完毕。
  • 显然在第一次 include"Animal.h" 时,#ifndef ANIMAL_H_H (ANIMAL_H_H  是没有被定义的),这个时候会将 Animal.h 内容拷贝到 Main.cpp 中,当再次 include"Fish.h"时,这个时候再次执行 #ifndef ANIMAL_H_H(ANIMAL_H_H  是有定义的,会直接跳出 中间的代码),走到#endif ,所以就不会报重复定义的问题

4.2 添加#pragma once程序编译一次

Animal.h

#pragma once
class Animal
{
public :
           Animal(int height, int weight) ;
           void eat() ;
           void sleep() ;
           virtual void breathe() ;
} ;
 
Fish.h

#pragma once
 
class Fish :public Animal
{
public :
      Fish() ;
      void breathe() ;
} ;

预处理阶段:

  1. 遇到①时,打开Animial.h,将#pragma once后面的内容包含进main.c中,关Animial.h。
  2. 遇到②时,打开Fish.h ,当试图打开 Animal.h时,发现在步骤一已经定义了一次,编译器直接跳过该语句,执行后面的语句,从而避免重复包含。

思考:

讲完了文件的重复包含,让我们来思考一个问题:如前所说,避免头文件的重复包含可以有效地避免变量的重复定义,其实不光是变量的重复定义,也可以避免函数和类、结构体的重复定义。但是
避免头文件的重复包含是否一定可以避免变量、函数、类、结构体的重复定义?

请看下面文章:C++:重定义:符号重定义:变量重定义

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值