自学C++之类的继承

来源:互联网 发布:淘宝网客服怎么联系 编辑:程序博客网 时间:2024/05/06 00:19

    继承是一种编程技术,可以从现有类中构造一个新类,通过新类实现面向对象的程序设计。

    类的继承的分类:1、单继承 2、多继承 3、虚继承


一、下面我们先来了解一下单继承;

    程序员能够根据已有类派生一个新类,这个新类继承了父类所有公有和受保护的数据成员和方法。

那么,什么是类的继承呢?

    类的继承--是指派生出来的类可以全部或者部分继承父类,同时,派生类还可以加入自己所需要的新特征和功能。简单的说,就是,派生类可以有选择性的继承父类的某些数据成员或者方法,同时,定义属于自己不属于父类的一些新的数据成员或者方法。

    新的类继承了原有类的特性,被称为原有类的派生类或者子类。而原有类被称为新类的基类或者父类。

单继承----就是以一个基类派生新类。

派生一个新类的格式:

   class  类名称 : 访问限定符(public 、protected、private)  基类名称

   例如:     class CDog : [public / protected / private] CAnimal {...........}

   在C++中有三种访问限定符

   1、访问限定符 public :表示,如果在父类中的public类型 的数据成员和方法,那么在子类中仍然是public 类型的。如果在父类中的protected类型的数据成员和方法,那么在子类中也是protected类型的数据成员和方法。

   2、访问限定符 protected :表示,如果在父类中的public 、protected类型的数据成员和方法,那么在子类中全部都变成了protected类型的数据成员和方法。

   3、访问限定符private :表示:如果在父类中的public 、protected 类型的数据成员和方法,那么在子类中全部都变成private类型的数据成员和方法。

#include "stdafx.h"
#include "string.h"

class CAnimal{
    //声明成员变量
    protected :
        char* m_name ;    //名称
        char* m_color ;    //颜色
    //定义4个方法,来获取和设置成员变量
    public:
        char* GetName() ;
        char* GetColor() ;
        void SetName(char* name) ;
        void SetColor(char* color) ;
        void Move() ;
        CAnimal() ;
        ~CAnimal() ;
} ;

char* CAnimal::GetName(){
    return m_name ;
}
char* CAnimal::GetColor(){
    return m_color ;
}

void CAnimal::SetName(char* name){
    strcpy(m_name,name) ;
}
void CAnimal::SetColor(char* color){
    strcpy(m_color,color) ;
}

CAnimal::CAnimal(){
    m_name = new char[5] ;
    m_color = new char[5] ;
}
CAnimal::~CAnimal(){
    delete []m_name ;
    delete []m_color ;
}

void CAnimal::Move(){
    printf("Animal is moving \n") ;
}

//现在定义一个CDog类,该类继承了基类CAnimal类,这样,CDog类就有了CAnimal类中所有非私有的数据成员和方法

class CDog : public CAnimal{
    protected :
        char* m_kind ;
    public :
        char* GetKind() ;
        void SetKind(char* kind) ;
        void yelp();
        CDog() ;
        ~CDog() ;
};

void CDog::yelp(){
    printf("Dog can yelp") ;
}
CDog::CDog(){
    m_kind = new char[10] ;
}
void CDog::SetKind(char* kind){
    strcpy(m_kind , kind) ;
}
char* CDog:: GetKind(){
    return m_kind ;
}

CDog::~CDog(){
    delete []m_kind ;
}


//主函数
int main(int argc, char* argv[])
{
    //实例化子类对象
    CDog dog ;
    dog.SetColor("白色") ;
    dog.SetName("狗") ;

    //调用父类的方法
    dog.Move() ;
    //调用自己的方法
    dog.yelp() ;
    printf("\n") ;
    return 0;
}
上面学习了单继承,了解了什么是单继承,现在来看一下,什么是多继承。

二、多继承

定义:多继承是指子类继承了多个父类。

语法:class 子类名称 : 访问限定符1  父类名称1  , 访问限定符2 父类名称2 , ........

    例如:class CWaterBird : public CBrid ,protected CFish {} ;

#include "stdafx.h"

class CBird{
    public :
        void fly() ;
        void move() ;
} ;

class CFish{
    public:
        void swim() ;
        void move() ;
} ;

//实例化方法
void CBird::fly(){
    printf("I can fly \n") ;
}
void CBird::move(){
    printf("bird can move \n") ;
}

void CFish::swim(){
    printf("I can swim \n") ;
}
void CFish::move(){
    printf("fish can move \n") ;
}

//CWaterBird继承CBrid和CFish类
class CWaterBird : public CBird ,public CFish {
    public :
        void run() ;
};

void CWaterBird ::run(){
    printf("waterBird can run \n") ;
}

int main(int argc ,char* argv[]){

    //实例化子类对象
    CWaterBird waterBird ;
    //调用父类CBird中的fly方法
    waterBird.fly();
    //调用父类CFish中的swim方法
    waterBird.swim() ;
    printf("\n") ;
    return 0 ;
}

注意:采用多继承会出现很多的问题。

    比如上面的类CBird和类CFish中都有move()方法。那么如果子类调用move方法,是调用哪个父类中的move方法呢?

waterBird.move(); //如果你是直接写这句,那么程序会报错。

【'CWaterBird::move' is ambiguous ,could be the 'move' in base 'CBird' of class 'CWaterBird',or the 'move' in base 'CFish' of class 'CWaterBird'】

这时,你就必须指明具体的调用哪个父类的方法

waterBird.CBird::move() ;

waterBird.CFish::move() ;

    还有一个问题就是:如果CBird和CFish类派生于同一个基类CAnimal,那么CWaterBird中就会有两个CAnimal对象,如果CWaterBird没有覆盖CAnimal类中的方法,如何调用CAnimal中的方法呢?

    如果你直接调用CAnimal中的方法,那么编译器会直接报错。

【'CWaterBird::breath' is ambiguous,could be the 'breath' in base 'CAnimal' of base 'CBird' of class 'CWaterBird',or the 'breath' in base 'CAnimal' of base 'CFish' of class 'CWaterBird'】

    编译器不知道调用的是CBird父类的方法还是CFish父类中的方法。那么怎么解决这个问题呢?和上面的类似,你需要指定类名称即可。

waterBird.CBird::breath() ;

貌似上面的方法有些麻烦,是吧。那么在C++中是否能够使CWaterBird类对象中只存在一个CAnimal对象呢?这样就可以直接调用CAnimal中的方法了。答案是有的。

三、虚继承

在C++中可以采用虚继承的方式来实现。用virtual关键字进行的继承叫做虚继承,当进行虚继承时,编译器会通过指针对其进行处理,使其只能产生一个基类子对象,这样的话,编译器就不会报错了。

语法:

class 子类名称 : virtual 访问限定符 基类名称

例如:class CBird : virtual public CAnimal

class CAnimal{
    public :
        void breath() ;
};

void CAnimal::breath(){
    printf("animal can breath \n") ;
}

class CBird : virtual public CAnimal{
    public :
        void fly() ;
        void move() ;
} ;

class CFish : virtual public CAnimal{
    public:
        void swim() ;
        void move() ;
} ;

//实例化方法
void CBird::fly(){
    printf("I can fly \n") ;
}
void CBird::move(){
    printf("bird can move \n") ;
}

void CFish::swim(){
    printf("I can swim \n") ;
}
void CFish::move(){
    printf("fish can move \n") ;
}

//CWaterBird继承CBrid和CFish类
class CWaterBird : public CBird ,public CFish {
    public :
        void run() ;
};

void CWaterBird ::run(){
    printf("waterBird can run \n") ;
}

int main(int argc ,char* argv[]){

    //实例化子类对象
    CWaterBird waterBird ;
    //调用breath方法
    waterBird.breath() ;
    printf("\n") ;
    return 0 ;
}

上述代码中,由于采用了虚继承,CWaterBird中只有一个CAnimal对象,因此可以直接调用CAnimal 中的方法,编译器不会报错。

0 0
原创粉丝点击