C++ 笔记 赋值兼容原则(公有继承)(面向对象)

在 C++公有继承 (public inheritance)场景下,赋值兼容原则 是面向对象多态特性的基础规则,也是实际开发中必须掌握的核心知识点。它定义了基类公有派生类 对象之间的赋值、转换规则,且这些转换是自动、安全、隐式的,无需强制类型转换。

一、核心概念

  1. 赋值兼容原则 :在公有继承中,派生类对象可以当作基类对象使用,基类的指针、引用可以指向、引用派生类对象。
  2. 前提条件 :必须是公有继承!私有继承、保护继承不满足该原则。
  3. 本质 :公有继承表达 is-a(是一个) 关系,派生类是基类的一种特例,因此可以自动向上匹配基类。

简单记:公有继承下,子类对象可以自动转换为父类对象

二、赋值兼容的四种典型用法(重点)

我们先定义基类和公有派生类,用于演示:

cpp 复制代码
#include <iostream>
using namespace std;

// 基类
class Base {
protected:
    int a;
public:
    Base(int x) : a(x) {}
    void show() {
        cout << "Base: a = " << a << endl;
    }
};

// 公有派生类
class Derived : public Base {
private:
    int b;
public:
    // 初始化基类
    Derived(int x, int y) : Base(x), b(y) {}
    void show() {
        cout << "Derived: a = " << a << ", b = " << b << endl;
    }
};

1. 派生类对象 赋值给 基类对象

派生类对象可以直接给基类对象赋值,只会赋值基类成员,派生类独有成员会被截断

cpp 复制代码
int main() {
    Derived d(10, 20); // 派生类对象
    Base b = d;        // 合法:派生类→基类(自动转换)
    b.show();          // 调用基类方法,输出:Base: a = 10
    return 0;
}

2. 派生类对象 初始化 基类引用

基类引用可以直接绑定派生类对象,引用的是基类部分,无截断、无拷贝

cpp 复制代码
Derived d(10, 20);
Base& ref = d; // 合法:基类引用指向派生类对象
ref.show();    // 调用基类方法

3. 基类指针 指向 派生类对象

基类指针可以直接指向派生类对象,这是多态的基础

cpp 复制代码
Derived d(10, 20);
Base* ptr = &d; // 合法:基类指针指向派生类对象
ptr->show();    // 调用基类方法

4. 派生类对象 作为函数参数(基类类型)

函数形参为基类对象 / 指针 / 引用时,可直接传入派生类对象,这是赋值兼容原则最常用的场景。

cpp 复制代码
// 函数参数是基类引用
void print(Base& obj) {
    obj.show();
}

int main() {
    Derived d(30, 40);
    print(d); // 直接传入派生类对象,自动转换
    return 0;
}

三、核心规则总结

  1. 只能向上转换:派生类 → 基类(自动、安全)
  2. 不能向下转换 :基类 → 派生类(不允许隐式转换 ,强行转换需用dynamic_cast,且有风险)
  3. 仅公有继承有效:private/protected 继承会破坏赋值兼容原则
  4. 转换后只能访问基类成员 :指针 / 引用指向派生类对象后,无法直接访问派生类独有成员

错误示例(基类指针访问派生类成员):

cpp 复制代码
Derived d(10,20);
Base* ptr = &d;
ptr->b; // 错误!基类没有b成员

四、为什么必须是公有继承?

公有继承 :表达 is-a(是一个)关系,派生类完全包含基类的所有公有 / 保护成员,外部可安全访问基类成员。

私有 / 保护继承 :表达 has-a(有一个)关系,基类成员在派生类中变为私有 / 保护,外部无法访问,不满足自动转换的安全性

示例:私有继承无法赋值兼容

cpp 复制代码
class Derived : private Base { ... };

Derived d;
Base b = d; // 错误!私有继承不允许转换

五、赋值兼容原则的意义

  1. 代码复用:一个函数可接收所有派生类对象,无需为每个子类写单独函数。
  2. 多态基础 :基类指针 / 引用指向派生类对象,配合虚函数实现运行时多态。
  3. 程序灵活:新增派生类时,基类接口无需修改,符合开闭原则。

六、易混点区分

  1. 赋值兼容 ≠ 类型相等 转换后只能用基类接口,不能用派生类独有成员。

  2. 向上转换安全,向下转换危险

    • 向上:派生类→基类(自动,安全)
    • 向下:基类→派生类(必须强转,不安全)
  3. 对象赋值会截断,指针 / 引用不会截断

    • 对象赋值:派生类独有成员丢失
    • 指针 / 引用:仅指向基类部分,对象本身无变化

总结(必背)

  1. 适用条件 :仅公有继承生效。
  2. 核心规则:派生类对象可自动转换为基类类型(对象、指针、引用)。
  3. 四种用法
    • 派生类对象 → 基类对象
    • 派生类对象 → 基类引用
    • 派生类对象地址 → 基类指针
    • 派生类对象 → 基类类型函数参数
  4. 核心价值:是 C++ 多态的前提,让代码更通用、更灵活。

赋值兼容原则是理解 C++ 继承与多态的必经之路,必须熟练掌握!

相关推荐
罗罗攀2 小时前
PyTorch学习笔记|单层神经网络
人工智能·pytorch·笔记·神经网络·学习
xyq20242 小时前
SQLite Insert 语句详解
开发语言
Hammer_Hans2 小时前
DFT笔记35
笔记
狼与自由2 小时前
AQS介绍
java·开发语言
森G4 小时前
29、QStringListModel 和 QListView---------Model/View模型视图
c++·qt
ouliten11 小时前
cuda编程笔记(37)--逐行量化的kernel分析
笔记
0xDevNull11 小时前
Java反射机制深度解析:从原理到实战
java·开发语言·后端
MimCyan11 小时前
面向开发者的 LLM 入门课程(个人笔记记录-2026.03.30)
笔记·ai
小小亮0111 小时前
Next.js基础
开发语言·前端·javascript