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++ 继承与多态的必经之路,必须熟练掌握!

相关推荐
csbysj2020几秒前
Web 品质样式表:构建高效、美观的网页设计指南
开发语言
小白学大数据2 分钟前
企业精准数据分析双路径对比:运营商大数据与 Python 爬虫技术选型与实践
大数据·开发语言·爬虫·python·数据分析
烛之武4 分钟前
《深度学习基础与概念》笔记(1)
人工智能·笔记·深度学习
ximu_polaris5 分钟前
设计模式(C++)-结构型模式-享元模式
c++·设计模式·享元模式
Hello!!!!!!7 分钟前
C++基础(五)——屏幕和文件输入输出
开发语言·c++·算法
ytttr8738 分钟前
C++ LZW 文件压缩算法实现
开发语言·c++
1candobetter12 分钟前
JAVA后端开发——多模块项目重命名体系解析
java·开发语言·intellij-idea
citi12 分钟前
OpenViking 本地搭建指南
开发语言·python·ai
AI玫瑰助手15 分钟前
Python基础:列表的切片与嵌套列表使用技巧
android·开发语言·python
RainCity16 分钟前
Java Swing 自定义组件库分享(二)
java·笔记