IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++的特质——继承 -> 正文阅读

[C++知识库]C++的特质——继承

继承

  • 被继承的作为父类(基类)
  • 继承父类的作为子类(派生类)
  • 子类继承父类的所有特性

对于继承的描述

  • 继承作为一个典型的树状结构
  • 从基类向下延伸,形成各种分支
  • 分支具有向上分支的特性,同时因自己的独特特性与其他分支区分开
  • 分支越向下必然是描述的越来越精细
  • 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有的特性基础上进行扩展,增加功能,增加属性,这样产生新的类,称作是派生类。
  • 继承呈现了面向对象程序设计的层析结构,体现了由简单到复杂的认知过程。继承是类设计层次的复用。
  • 举例: 以people类作为基类,向下延伸的student类,teacher类,worker类,这样的类之后再延伸出带有新的特性的子类
    以people->worker->salesman为例,salesman具有其worker的特性,区别于worker,salesman多出了自己的新特性,新的功能。

继承程序举例

#include <iostream>
#include <string>
using namespace std;

class people
{

public:
    people(string name, string sex, int age) : m_name(name), m_sex(sex), m_age(age){};

public:
    string m_name;
    string m_sex;
    int m_age;
};

class student : public people
{
public:
    student(string name, string sex, int age, int sid) : people(name, sex, age), m_sid(sid){};

    void print_s()
    {
        cout << m_name << ","
             << m_sex << ","
             << m_age << ","
             << m_sid << endl;
    }

public:
    int m_sid;
};

class representative : public student
{
public:
    representative(string name, string sex, int age, int sid, string course) : student(name, sex, age, sid), m_course(course){};

    void print_r()
    {
        cout << m_name << ","
             << m_sex << ","
             << m_age << ","
             << m_sid << ","
             << m_course << endl;
    }

public:
    string m_course;
};

int main()
{
    representative r("王明", "男", 20, 1, "数学");
    r.print_s();
    cout << endl;
    r.print_r();
    return 0;
}

运行结果:

王明,,20,1

王明,,20,1,数学
  • 上例实现的是公有成员与公有继承。保护成员与继承、私有成员与继承的实现读者可以自行尝试。
    以上程序,旨在于体现继承的作用,子类继承父类的属性与方法,并可以实现调用父类的方法

Tips

  • 子类拥有父类的所有特性
  • 继承方式有公有继承,私有继承,保护继承。默认是私有继承。
  • 公有继承中父类的公有和保护成员在子类中不变,私有的在子类中不可访问。(public)
  • 私有继承中父类的公有和保护成员在子类中变为私有,但私有的在子类中不可访问。(private)
  • 保护继承中父类的公有和保护成员在子类中变为保护,但私有的在子类中不可访问。(protected)

继承的优缺点

  1. 首先,最明显的好处,顾名思义的继承,父辈走过的路,后辈如果想去走相同的路的话,不用再走一遍,父辈的工具(定义好的函数方法)与经验(定义好的使用方法需要的属性),只要后辈继承了,那就都属于后辈,减少重复的代码,父辈私有(private)的除外
  2. 增加了类之间的关联程度,即耦合度(既是优点,也是缺点)
  3. 继承的使用就意味着父类至少定义了子类的部分行为,父类的改变会影响所有继承的该父类的子类
  4. 子类会直接拷贝父类的内存空间,如果父类继承的东西,子类没有都用到,就是浪费空间,少用一个就多浪费一点。当然,这个浪费只是这样说,只要不是父类弄的特别大特别全,然后继承过来就用一点,都不算太过分。总的来说,继承减少了代码量,但是该给的内存空间一点没少,多数情况还要多出一点作为没有使用到拷贝空间的所有内容的浪费。

关于继承体系中的成员函数的几种情况

重载:写一个与已有函数同名但是参数列表不同的函数

重写:对函数的重写,函数列表与参数列表都相同,但是对内部实现进行修改

隐藏:子类对象、指针、引用访问基类和派生类都有同名函数时,先访问子类的函数,即隐藏父类的同名函数。更通俗的讲,父类定义过的函数,子类又重新定义了一次,这时子类对象用函数,优先用子类里面的,子类里面找不到再往上找。

继承体系里几种情况,相比较的关系

继承体系同名成员函数的关系
作用域函数名称参数返回值
重载同一作用域相同名称不同可以不同
隐藏(覆盖)不同作用域,父类与子类相同名称相同相同
重写不同作用域,父类与子类,父类中必须要有virtual相同名称相同相同(协变除外)

对继承的补充:

一,多继承

子类只继承一个父类的情况被称为单继承
此外,C++也支持多继承,即一个子类继承了多个父类——多继承
形如:

class C : public A, public B//这里的继承的方式不止于public,protected、private都可以正常使用,与正常的继承方式相同,多继承只是多了父类,没有什么特别的。
{
}

多继承下的构造函数如果想要调用不同父类中的参数,当然也不同于单继承
形如:

class C : public A, public B
{
public:
    C(int a, int b, int c) : A(a), B(b)//多继承下的构造函数
    {
    }
    ~C()
    {
    }
    int m_c;
};

多继承完整程序举例:

#include "iostream"
using namespace std;

class A
{
public:
    A(int a)
    {
    }
    ~A()
    {
    }
    int m_a;
};

class B
{
public:
    B(int b)
    {
    }
    ~B()
    {
    }
    int m_b;
};

class C : public A, public B
{
public:
    C(int a, int b, int c) : A(a), B(b)
    {
    }
    ~C()
    {
    }

    int m_c;
};

int main()
{
    C c(1, 2, 3);

    cout << &c << endl;
    cout << &c.m_a << endl;
    cout << &c.m_b << endl;
    cout << &c.m_c << endl;

    cout << sizeof(c) << endl;

    return 0;
}

二,虚继承

虚继承作为解决多继承产生的问题的一种手段。

多继承主要产生两种问题:

  1. 多个子类继承了同一父类,每个子类都拷贝了一份父类的内存空间,显而易见,浪费了存储空间
  2. 数据的二义性问题。具体的举例来说,“菱形”问题:有最基类A,有A的派生类B、C,又有D同时继承B、C,那么若A中有成员a,那么在派生类B,C中就存在a,又D继承了B,C,那么D中便同时存在B继承A的a和C继承A的a,那么当D的实例调用a的时候就不知道该调用B的a还是C的a,就导致了二义性。

菱形二义性的解决:

  1. 作用域限定符,‘’::‘’,明确的指出来,谁是谁的谁
  2. 在子类中定义同名的成员覆盖掉父类继承过来的成员。只是不报错了,相对应的,父类继承过来的成员也不能直接用了
  3. 虚继承:父类对祖父类的继承改为虚继承(virtual),各父类共享一个祖父类的拷贝,那么子类从父类继承过来的祖父类成员也就只有一个了。

菱形继承的解决代码举例:

#include "iostream"
using namespace std;

class A
{
public:
    A(int a) {}
    ~A() {}

    int m_a;
};

class B : virtual public A
{
public:
    B(int a, int b) : A(a) {}
    ~B() {}

    int m_b;
};

class C : virtual public A
{
public:
    C(int a, int c) : A(a) {}
    ~C() {}

    int m_c;
};

class D : public B, public C
{
public:
    D(int a, int b, int c, int d) : A(a), B(a, b), C(a, c)
    {
        m_a = a;
        m_b = b;
        m_c = c;
        m_d = d;
    }
    ~D() {}

    int m_d;
};

int main()
{
    D d(1, 2, 3, 4);

    cout << d.m_a << endl;
    cout << sizeof(d) << endl;

    cout << &d << endl;
    cout << &d.m_a << endl;
    cout << &d.m_b << endl;
    cout << &d.m_c << endl;
    cout << &d.m_d << endl;

    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-26 09:58:18  更:2021-09-26 10:00:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 17:44:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码