C++学习总结-继承

目录

概述

概念

定义

基类与派生类对象赋值转换

基类指针与引用

 派生类对象转换为基类对象

基类对象转换为派生类对象

继承中的作用域

成员隐藏

借助作用域解析运算符访问被隐藏的成员 

成员变量的隐藏

使用using声明引入基类成员

派生类的默认成员函数

继承与友元

继承与静态成员

单继承 多继承  菱形继承

虚基表


概述

概念

继承面向编程三大思想之一,它允许一个类(该类一般称为子类或者派生类)从另一个类(父类或者基类)中继承属性和方法。利用继承,子类可以重用父类的代码的同时,拓展和修改父类的行为。

继承涉及的概念

  • 基类:也就是父类,其主要被子类继承
  • 派生类:子类,继承子父类,在拥有父类代码的同时还可以拓展自己的功能
  • 访问控制
    • public继承:基类public成员在派生类也是public;基类中protected成员在派生类中也是protected
    • protected继承:基类的public成员和protected成员在派生类中都会变成protected
    • private继承:基类的public成员和protected成员在派生类中都变成private类型
    • 总结:以上无论那种继承方式,都无法访问父类的Private 成员,这类似父类的小秘密,不想被其他派生类继承。 
#include <iostream>
using namespace std;

class Base {
public:
    int publicVar;
protected:
    int protectedVar;
private:
    int privateVar;
};

class DerivedPublic : public Base {
public:
    void accessMembers() {
        publicVar = 1;       // 可以访问
        protectedVar = 2;    // 可以访问
        // privateVar = 3;   // 不能访问
    }
};

class DerivedProtected : protected Base {
public:
    void accessMembers() {
        publicVar = 1;       // 可以访问
        protectedVar = 2;    // 可以访问
        // privateVar = 3;   // 不能访问
    }
};

class DerivedPrivate : private Base {
public:
    void accessMembers() {
        publicVar = 1;       // 可以访问
        protectedVar = 2;    // 可以访问
        // privateVar = 3;   // 不能访问
    }
};

int main() {
    DerivedPublic dp;
    dp.publicVar = 1;       // 可以访问
    // dp.protectedVar = 2; // 不能访问

    DerivedProtected dpr;
    // dpr.publicVar = 1;   // 不能访问

    DerivedPrivate dpv;
    // dpv.publicVar = 1;   // 不能访问

    return 0;
}

定义

继承基类成员访问方式变化总结 

  • 基类private成员,无论哪种方式继承,派生类中都不可见
  • class默认继承方式是private,struct的默认继承方式是public,所以如果涉及到继承的时候,需要关注其成员变量和函数的类型
类成员/继承方式public继承  protected继承private继承
基类public继承派生类的public派生类的protected派生类的private
基类protected继承派生类protected派生类的protected派生类的private
基类的private继承派生类不可见派生类不可见派生类不可见

基类与派生类对象赋值转换

总结

  • 基类指针和引用可以指向派生类对象,这使得多态性成为可能。
  • 派生类对象转换为基类对象时会发生对象切片,派生类的特定部分会被丢弃。
  • 基类对象不能直接转换为派生类对象,需要使用 dynamic_cast 来进行安全的类型转换

基类指针与引用

基类指针和引用可以指向派生类对象

 派生类对象转换为基类对象

派生类对象被转换为基类对象的时候,会发生对象切片,即派生类的对象中与基类不同的部分会被切除。

 

基类对象转换为派生类对象

基类对象是不可以直接转换为派生类对象的,因为基类对象不包含派生类的成员。如果需要对其进行强转,则必须保证基类对象实际是某个派生类对象的子对象,同时使用类型转换操作符 dynamic_cast 

继承中的作用域

总结

  • 成员隐藏:派生类中同名成员会隐藏基类中的成员
  • 作用域解析运算符:使用::可以访问被隐藏的基类成员
  • 成员变量的隐藏:类似于成员函数,派生类中的同名成员变量会隐藏基类中的成员变量
  • 使用using声明:可以引入基类成员以避免隐藏

成员隐藏

派生类中如果定义了与基类中相同的成员函数或者变量,基类中的成员将会被隐藏

借助作用域解析运算符访问被隐藏的成员 

成员变量的隐藏

 下面代码中,隐藏了基类中的value的数值,而是只显示子类的数值

使用using声明引入基类成员

 代码中可以借助using 声明,将基类中的成员引入到派生类中使用

派生类的默认成员函数

总结

  • 默认构造函数:派生类的默认构造函数会调用基类的默认构造函数去初始化基类的部分代码
  • 拷贝构造函数:派生类的默认拷贝函数调用基类的拷贝构造函数来复制基类部分
  • 赋值操作符:派生类默认赋值操作符则是调用基类的赋值操作符完成基类的复制
  • 析构函数:派生类调用基类的析构函数析构基类的部分,如果基类的析构函数是虚函数,即派生类的析构函数也是虚函数
  • 移动构造和移动赋值操作符:同上

派生类中默认成员函数,其中基类代码,都是去调用基类的默认成员函数完成。

继承与友元

  • 友元关系是不可以被继承的,即基类的友元是无法访问其子类私有成员和保护成员的
  • 派生类可以通过基类的友元来访问基类的私有成员

继承与静态成员

总结

  • 静态成员变量在派生类中仍然是属于基类的,其可以通过或派生类来访问,但是其在内存中只存在唯一一个
  • 静态成员函数
    • 可以被派生类继承和隐藏,同样可以通过基类或派生类名对其进行访问

单继承 多继承  菱形继承

单继承:一个派生类只能够有一个直接的基类

 多继承:一个派生类中用于很多直接的基类,从而从多个基类中继承属性和方法

 菱形继承:一个类从两个基类中继承,然而这两个基类又是继承自同一个基类。菱形继承会导致数据成员的多次拷贝,从而引发二义性问题,主要解决办法则是利用虚继承。

虚基表

 实现分析

  • 类定义:每个含有虚函数的类都有一张虚函数表,表内存储虚函数的地址
  • 对象实例化: 对象在实例化后,包含有一个指向虚基表的指针,构造函数初始化该指针
  • 虚基类访问:通过虚基表中的偏移量,确保正确访问到虚基类的成员

Derived1和Derived2因为是虚继承,内部都有一个指向虚基表的指针,可以通过该指针访问基类中的函数以及内容。 具体来说是通过虚指针到虚基表中找到继承基类函数的首地址进行访问。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值