C++的继承

C++的继承

继承的基础语法

C++继承是一个类(派生类)继承了另一个类(基类)的所有成员(成员变量和成员函数),除了构造函数、析构函数以及被声明为私有的成员之外。

继承的定义格式:

继承方式:

【注意点】:

  1. 同名隐藏:如果派生类定义了一个与基类同名的成员(包括成员变量或成员函数),那么派生类的成员将会隐藏基类的成员。可以使用 作用域解析运算符:: 来明确引用基类的成员。

(尽量避免同名,同名函数不会构成重载,重载要求在相同的作用域中,而基类和派生类都有独立的作用域)

  1. 友元和静态成员:友元关系不被继承。静态成员属于整个类,而不是某个特定的对象实例,因此无论是基类还是派生类共享相同的静态成员。

基类和派生类对象的赋值转换

  • 派生类对象可以赋值给 基类的对象/基类的指针/基类的引用。
    (形象说法 "切片",寓意把派生类中父类那部分切来赋值过去)
cpp 复制代码
//赋值兼容 (切片)
Student s;

Person p = s;
Person* pp = &s;
Person& rp = s;

//不会产生中间临时变量,没有发生类型转换
  • 基类对象不能直接赋值给派生类对象。
  • 基类的指针或引用可以强制类型转换赋值给派生类的指针或引用。
    (必须是基类的指针指向派生类对象才是安全的)

派生类的默认成员函数

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。


  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化,派生类的operator= 要调用基类的operator= 完成基类的复制,没有默认的需显式调用。



  3. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员,以保证派生类对象先清理派生类成员,再清理基类成员的顺序。

    (因为析构函数会被统一重写为destructor(),所以基类的析构函数应该声明为virtual)

  4. 派生类对象初始化先调用基类构造,再调派生类构造。

  因为子类可能依赖于父类的成员变量或方法,这些都需要在子类构造之前被正确初始化,所有先构造父类;而析构先释放子类特有的资源,再释放父类资源,是为了避免访问已释放的资源。

菱形继承和菱形虚拟继承

菱形继承:菱形继承是多继承的一种特殊情况。

虚拟继承的写法:

菱形中间有成员被重复继承的两个类,继承方式前加上 virtual 。

这样就解决了数据冗余和访问二义性的问题。为了实现这一点,编译器会在 Student 和 Teacher 类的对象布局中各添加一个指向共享的 Person 实例的指针,这个指针通常被称为虚基表指针(vbptr),它指向同一个虚基表(vbtable),该表记录了如何从各自独有的对象所处于位置到共享对象的偏移量。

IDE里的实例:

虚拟继承总结:知道这个处理办法就行,写代码时尽量避免菱形继承。

相关推荐
大圣编程32 分钟前
Python中continue语句的用法是什么?
开发语言·前端·python
upgrador1 小时前
基础知识:C++ STL构造函数的左闭右开惯例及其实现原理
开发语言·c++
yoothey2 小时前
报废审批流规则引擎设计——责任链模式完整实现
linux·开发语言·bash
geovindu2 小时前
python: Functional Options Pattern
开发语言·后端·python·设计模式·惯用法模式·函数式选项模式
wuyk5552 小时前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机
凯瑟琳.奥古斯特3 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展
林中青木3 小时前
CT重构原理及C++代码实现
c++·计算机视觉·重构
AC赳赳老秦3 小时前
防火墙规则批量配置实战:OpenClaw 自动生成模板、批量下发与合规性校验全解析
java·开发语言·人工智能·python·github·php·openclaw
满天星83035773 小时前
Protobuf的介绍及使用
c++
☆cwlulu3 小时前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu