初学C++之类的继承与派生及多态

一. 基本概念

继承是面向对象程序设计中最重要的一个概念,继承允许我们根据一个类的定义来定义另一个类,达到代码重用的效果.
当创建一个类时,如果待创建的类与另一个类存在某个共同的特征,那就可以不用重写成员变量和成员函数,只需要指定继承另一个类即可.被继承的类称为父类或基类,新建的类称为子类或派生类,

二. 基类和派生类

定义一个派生类, 需要指定它的基类,语法如下:
class derived-class:access-specifier base-class

  • derived-class: 派生类的名称
  • access-specifier: 访问修饰符,可选值为[public, private|protected],缺省值为:private
  • base-class: 基类,是之前定义过的一个类的名称,
    代码示例(已通过g++编译,运行OK):
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<string>
#include<vector>  // vector 需要的包含的头文件
#include<algorithm>
class CGirl{  // 定义一个超女类
    public:
        char m_name[50]; // 姓名
        int m_age;  // 年龄
        int m_height;  // 体重
        char m_sc[30];   // 身材
        char m_yz[30];  // 颜值

        int Show();  //显示超女基本信息的成员函数
};


class CKCon:public CGirl{   // 定义王妃类, 从超女继承
    public:
        char m_ch[50]; // 称号
        char m_palace[50]; //居住的宫殿
        int m_sal; //俸禄

        int Show();  // 重载基类的成员函数
};

int main() {
    CKCon KCon; // 实例化一个KCon对象
    strcpy(KCon.m_name, "张大");
    KCon.m_age=19;
    KCon.m_height=49;
    strcpy(KCon.m_sc, "苗条");
    strcpy(KCon.m_yz, "漂亮");
    strcpy(KCon.m_ch, "王妃");
    strcpy(KCon.m_yz, "什么宫");
    KCon.m_height=449;
    KCon.Show();  // 
}

int CGirl::Show(){
    printf("name=%s, age=%d, height=%d, sc=%s, yz=%s\n", m_name, m_age, m_height,m_sc,m_yz);
    return 0;
}

int CKCon::Show(){
    printf("name=%s, age=%d, height=%d, sc=%s, yz=%s, ", m_name, m_age, m_height,m_sc,m_yz);
    printf("ch=%s, palace=%s, sal=%d\n", m_ch, m_palace,m_sal);

    return 0;
}

代码演示结论:

  • 派生类可以重载基类的成员函数(与python的类继承是一致的)

三.访问控制和继承

3.1 访问控制

  • 派生类可以访问基类中所有的非私成员变量和成员函数, 如果基类的成员变量和成员函数不想被派生类访问, 则应在基类中声明为: private

3.2 继承类型

当一个类派生自一个基类, 该基类可以被继承为public, pricate和protected三种类型,

实际开发中,通常使用public, 其它的很少使用

当使用不同类型的继承时,遵循以下几个规则:

  • public: 当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员, 基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问, 但是可以通过调用基类的公有成员和保护成员来访问.
  • protected: 当一个类派生自保护基类时, 基类的公有和保护成员将成为派生类的保护成员.
  • pricate: 当一个类派生自私有基类时,基类的公有和保护成中将成为派生类的私有成员.

四. 基类与派生类的指针

  • 基类的指针可以指向基类对象, 还可以指向派生类对象, 但不能通过基类的指针访问派生类的成员.
  • 派生类的指针可以指向派生类的对象,不可以指向基类对象.
    后面代码有演示

五.多继承

多继承即一个派生类可以有多个基类,它继承了多个基类的特性.

类的继承与派生在windows环境中用得比较多, 在linux中用的很少, 多继承的应用场景更少.

六. 类的多态

当类之间存在层次结构,并且类之间是通过继承关联时,就可以会用到多态.
C++多态就是当调用成员函数时, 会根据调用函数的对象的类型来执行不同的函数.

在成员函数的声明前, 放置关键字: virtual,
这是多态的一般使用方式,有了多态, 就可以有多个不同的类,都带有同一个名称但具有实现不同功能的函数.

#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<string>
#include<vector>  // vector 需要的包含的头文件
#include<algorithm>
class CGirl{  // 定义一个超女类
    public:
        char m_name[50]; // 姓名
        int m_age;  // 年龄
        int m_height;  // 体重
        char m_sc[30];   // 身材
        char m_yz[30];  // 颜值

		// virtual int Show()=0;  // 这是定义了6.2中的纯虚函数.
        // virtual int Show() // 添加了virtual关键字, 注意执行结果的区别
        int Show();  //显示超女基本信息的成员函数
};


class CKCon:public CGirl{   // 定义王妃类, 从超女继承
    public:
        char m_ch[50]; // 称号
        char m_palace[50]; //居住的宫殿
        int m_sal; //俸禄

        int Show();
};

int main() {
    CKCon KCon; // 实例化一个KCon对象
    strcpy(KCon.m_name, "张大");
    KCon.m_age=19;
    KCon.m_height=49;
    strcpy(KCon.m_sc, "苗条");
    strcpy(KCon.m_yz, "漂亮");
    strcpy(KCon.m_ch, "王妃");
    strcpy(KCon.m_yz, "什么宫");
    KCon.m_height=449;


    // KCon.Show();  // 执行派生类的成员函数

    CGirl *p1;  // 基类的指针
    CKCon *p2;  // 派生类的指针

    p1=p2=&KCon;  // 都指向派生类

    p1->Show();   // 将调用基类的Show成员函数
    p2->Show();  // 将调用派生类的Show成员函数
    return 0;
}

int CGirl::Show(){
    printf("name=%s, age=%d, height=%d, sc=%s, yz=%s\n", m_name, m_age, m_height,m_sc,m_yz);
    return 0;
}

int CKCon::Show(){
    printf("name=%s, age=%d, height=%d, sc=%s, yz=%s, 称号=%s, palace=%s, sal=%d\n",m_name,m_age,m_height,m_sc,m_yz, m_ch, m_palace,m_sal);

    return 0;
}

程序经过运行后发现:

  1. 若基类的成员函数带有关键字: virtual, 派生类有同名的成员函数, 则基类指针和派生类指针都将指向派生类的成员函数
  2. 若基类的成员函数带有关键字: virtual, 派生类没有同名的成员函数, 则基类指针和派生类指针都将指向基类的成员函数
  3. 若基类的成员函数没有关键字: virtual, 派生类有同名的成员函数, 则基类指针指向基类的成员函数,派生类指针指向派生类的成员函数
  4. 若基类的成员函数没有关键字: virtual, 派生类没有同名的成员函数, 则基类指针和派生类指针都将指向基类的成员函数

6.1 虚函数

虚函数是在基类中使用关键字virtual声明的函数,在派生类中重新定义已在基类中完成定义的虚函数时, 会告诉编译器不要静态链接到该函数.
在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作称为动态链接或后期绑定

6.2 纯虚函数

在基类中定义纯虚函数,以便在派生类中重新定义该函数更好地适用于对象, 但在基类中又不能对虚函数给出有意义的实现,此时就会用到纯虚函数

个人理解: 与python中的@abstractmethod, 在基类中定义一个成员函数, 没有具体的功能,可以理解为是个占位符, 但不能被实例化, 只在派生类中重写该成员函数,实现派生类的成员函数的功能 .

6.3 C++接口 (抽象类)

接口描述了类的行为和功能,是标准和规范,而不需要完成功能的实现.
C++接口是使用抽象类来实现的,如果类有一个纯虚函数,则这个类就是抽象类.
设计抽象类的目的,是为了给其他类提供一个可以继承的适当的基类,抽象类不能用被用于实例化对象, 它只能作为接口使用,否则编译错误.

  • 一个基类的派生类需要被实例化,则必须实现每个纯虚函数, 这意味着C++支持使用基类申明接口. 如果派生类没有实现基类中所有的纯虚函数,就要实例化,则会导致编译错误.
  • 可用于实例化的类称为具体类,

这些使用场景并不多.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值