跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++

C++ 继承机制详解:概念、访问控制与转换

综述由AI生成C++ 继承是面向对象的核心特性,允许派生类复用基类成员并扩展功能。文章涵盖继承定义、访问权限变化(public/protected/private)、模板继承示例以及基派生类转换规则。重点解析了切片现象、强制类型转换风险及动态类型识别(dynamic_cast)的应用场景,帮助开发者理解如何安全高效地构建类层次结构。

雾岛听风发布于 2026/3/15更新于 2026/4/306 浏览
C++ 继承机制详解:概念、访问控制与转换

继承

继承(Inheritance)是面向对象程序设计中实现代码复用的核心手段。它允许我们在保持基类特性的基础上进行扩展,增加新的成员函数和属性,从而生成派生类。

1. 继承的概念

假设我们有两个类 Student 和 Teacher,它们都包含姓名、地址、年龄、电话等公共成员,以及身份认证功能。如果分别定义,代码会非常冗余。

class Student {
public:
    // 进入校园/图书馆刷二维码等身份认证
    void identity() {
        // ...
    }
    // 学习
    void study() {
        // ...
    }
protected:
    string _name = "peter";
    string _address;
    string _tel;
    int _age = 18;
    int _stuid;
};

class Teacher {
public:
    void identity() {
        // ...
    }
    // 授课
    void teaching() {
        // ...
    }
protected:
    string _name = "张三";
    int _age = 18;
    string _address;
    string _tel;
    string _title;
};

int main() {
    return 0;
}

我们可以将公共成员提取到 Person 类中,让 Student 和 Teacher 继承 Person,这样就能复用这些成员,避免重复定义。

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

class Person {
public:
    void identity() {
        cout << "void identity()" << _name << endl;
    }
protected:
    string _name = "张三";
    string _address;
    string _tel;
    int _age = 18;
};

class Student : public Person {
public:
    void study() {
        // ...
    }
protected:
    int _stuid;
};

class Teacher : public Person {
public:
    void teaching() {
        // ...
    }
protected:
    string title;
};

int main() {
    Student s;
    Teacher t;
    s.identity();
    t.identity();
    return 0;
}

2. 继承的定义

Person 称为基类(父类),Student 称为派生类(子类)。翻译习惯上两者通用。

继承关系示意图

2.1 定义格式
class DerivedClass : access_mode BaseClass {
    // ...
};
2.2 继承方式与成员访问权限
类成员 / 继承方式public 继承protected 继承private 继承
基类的 public 成员派生类的 public 成员派生类的 protected 成员派生类的 private 成员
基类的 protected 成员派生类的 protected 成员派生类的 protected 成员派生类的 private 成员
基类的 private 成员在派生类中不可见在派生类中不可见在派生类中不可见

这里需要特别注意几点:

  1. 私有成员的可见性:基类的 private 成员无论以何种方式继承,在派生类中都是不可见的。注意,不可见是指语法限制,对象内存中其实包含了这部分数据,只是无法直接访问。
  2. 保护成员的作用:如果基类成员不想在类外被直接访问,但需要在派生类中使用,应定义为 protected。这是因继承而引入的限定符。
  3. 访问规则总结:基类的其他成员在派生类的访问权限等于 min(基类访问限定符,继承方式)。顺序为 public > protected > private。
  4. 默认继承方式:使用关键字 class 时默认为 private 继承,使用 struct 时默认为 public 继承。实际开发中建议显式写出继承方式。
  5. 最佳实践:实际运用中一般使用 public 继承。protected/private 继承下来的成员只能在派生类内部使用,扩展性和维护性较差,不提倡滥用。

3. 模板继承示例

标准库中的 stack 容器适配器就是基于 vector 实现的典型例子,既符合 is-a 关系,也体现了 has-a 的组合思想。

namespace jiang {
template<class T>
class stack : public std::vector<T> {
public:
    void push(const T& x) {
        // 基类是类模板时,需要指定作用域,否则编译报错
        // error C3861: 'push_back': 找不到标识符
        // 因为 stack<int> 实例化时,vector<int> 也被实例化了
        // 但模版按需实例化,push_back 等成员函数可能未实例化
        vector<T>::push_back(x);
    }
    void pop() {
        vector<T>::pop_back();
    }
    const T& top() {
        return vector<T>::back();
    }
    bool empty() {
        return vector<T>::empty();
    }
};
}

int main() {
    jiang::stack<int> st;
    st.push(1);
    st.push(2);
    st.push(3);
    while (!st.empty()) {
        cout << st.top() << " ";
        st.pop();
    }
    return 0;
}

4. 基类和派生类之间的转换

在涉及多态或接口设计时,理解类型转换至关重要。

  1. 向上转换(Upcasting):public 继承的派生类对象可以赋值给基类的指针或引用。这被称为'切片'或切割,寓意把派生类中基类那部分切出来,基类指针指向的是派生类对象中属于基类的那部分数据。
  2. 向下转换(Downcasting):基类对象不能直接赋值给派生类对象。基类指针或引用可以通过强制类型转换赋值给派生类指针或引用,但必须确保基类指针确实指向了派生类对象,否则不安全。
  3. 安全转换:如果基类是多态类型(含有虚函数),可以使用 RTTI(Run-Time Type Information)的 dynamic_cast 进行识别后再转换。

类型转换示意图

int main() {
    jiang::stack<int> st;
    st.push(1);
    st.push(2);
    st.push(3);
    while (!st.empty()) {
        cout << st.top() << " ";
        st.pop();
    }
    return 0;
}

class Person {
protected:
    string _name;
    string _sex;
    int _age;
};

class Student : public Person {
public:
    int _No;
};

int main() {
    Student sobj;
    // 1. 派生类对象可以赋值给基类的指针/引用
    Person* pp = &sobj;
    Person& rp = sobj;
    // 派生类对象赋值给基类对象是通过调用基类的拷贝构造完成的
    Person pobj = sobj;

    // 2. 基类对象不能赋值给派生类对象,这会编译报错
    // sobj = pobj; 
    return 0;
}

在实际开发中,尽量利用向上转换带来的多态特性,谨慎处理向下转换,必要时配合 dynamic_cast 确保类型安全。

目录

  1. 继承
  2. 1. 继承的概念
  3. 2. 继承的定义
  4. 2.1 定义格式
  5. 2.2 继承方式与成员访问权限
  6. 3. 模板继承示例
  7. 4. 基类和派生类之间的转换
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 在安卓手机或平板上使用 Termux 搭建 Debian 环境并运行 PC 级 Linux 应用
  • 基于 Higress 将 REST API 转换为 MCP Server 工具
  • FAIR plus 2026 机器人全产业链接会前瞻
  • Tomcat 入门与服务器端口配置指南
  • Drupal 7 核心模块与常用扩展功能梳理
  • Git 与 TortoiseGit 安装配置实战指南
  • Spring 加载 XML 配置文件的六种常用方式
  • Flutter 底部导航与顶部选项卡多页切换实战
  • Coze 全解析:100 个落地用途与发布使用指南
  • GitHub Copilot 最新演进:从代码补全到需求理解
  • Javashop 百万级并发压力测试与性能优化分析
  • 大语言模型 (LLM) 高频面试题及答案汇总
  • 2026 年 3 月大模型全景解析:国产登顶、百万上下文落地与 Agent 工业化
  • Python 七大学习路线详解
  • Python 与前端集成:构建全栈应用
  • 模拟算法实战:替换问号、提莫攻击、N 字形变换、外观数列与数青蛙
  • Swagger MCP 实战:基于 Spring Boot 与 Spring AI 将 OpenAPI 转为工具
  • IQuest-Coder-V1 vs Meta-Llama-Code:指令模型精度实测
  • ToDesk 顺网云 海马云部署 DeepSeek 对比评测
  • OpenHarmony 开发:使用 cached_query 实现高性能声明式数据缓存

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online