当前位置: 首页 > news >正文

【经典书籍】C++ Primer 第13类继承精华讲解

今天我们就来生动、易懂、接地气地详细讲解《C++ Primer》第13章的内容


📘 《C++ Primer》第13章:类继承(Class Inheritance)


🎯 一句话概括本章是干嘛的?

第13章教你如何在 C++ 中让一个类(子类/派生类)继承另一个类(父类/基类)的特性,实现“代码复用 + 功能扩展”的超能力!

你可以理解为:

“儿子继承爸爸的财产和基因,同时还能发展自己的特长。”

→ 类继承就是:子类继承父类的成员(数据+函数),并可以新增或重写功能。


🧩 一、为什么要用继承?(现实意义)

想象这样一个场景:

你正在开发一个游戏,里面有各种各样的角色:

  • 普通角色:有名字、血量、可以行走、可以说话

  • 战士:是角色的一种,除了基本功能,还能攻击

  • 法师:也是角色的一种,会施法

  • 盗贼:会潜行、偷窃

如果为每个角色都从头写代码,那 name、hp、walk()、talk() 这些重复的代码你得写好几遍!

👉 继承就是让你把公共的部分(比如角色的基本属性和行为)放到一个“父类”里,然后“子类”继承它,并加上自己独有的技能!


🧠 二、核心概念(用大白话讲清楚)

我们来逐个击破第13章的几个关键概念,用生活化 + 代码示例的方式帮你彻底理解!


1️⃣ 什么是继承(Inheritance)?

继承就是:让一个类(子类/派生类)基于另一个类(父类/基类),自动拥有它的成员,并可以扩展或修改。

🧬 类比:家族遗传

  • 父类(基类):就像你爸,他有名字、年龄、会走路、会说话

  • 子类(派生类):就像你,你继承了他的名字、年龄、走路说话能力,但你还会打篮球、弹吉他

在 C++ 中:

// 父类(基类)
class Person {
public:void walk() { std::cout << "Walking...\n"; }void talk() { std::cout << "Talking...\n"; }
};// 子类(派生类)
class Student : public Person {  // 👈 继承 Person
public:void study() { std::cout << "Studying...\n"; }
};

👉 Student “继承”了 Person 的 walk() 和 talk(),同时还能 study()!


2️⃣ 继承的语法:class 派生类 : 访问级别 基类

语法格式:

class 派生类名 : 访问修饰符 基类名 {// 派生类特有的成员
};

其中,访问修饰符可以是:

关键字含义
public父类的 public 成员在子类中仍然是 public,protected 同理
protected父类的 public/protected 成员在子类中都变为 protected
private父类的所有成员在子类中都变为 private(很少用)

🔒 最常用的是 public 继承,表示“是一个(is-a)”的关系,比如“学生是一个人”。


3️⃣ 什么是“is-a”关系?(继承的核心思想)

继承表达的是一种“是一个”的关系,而不是“有一个”的关系。

正确用法(is-a)错误用法(has-a,应该用组合而不是继承)
学生是一个人车有一个引擎(应该用成员变量,不是继承)
战士是一个角色房子有一扇门
信用卡是一个账户 

🔑 记住:能用继承的,一定是“子类 is a kind of 父类”。


🧩 三、继承后,成员的访问权限变化(重点!)

这是第13章一个比较绕,但非常重要的部分👇

父类的成员有三种访问级别:

访问级别谁能访问?
public任何人(类外也可以通过对象访问)
protected本类 + 子类 可以访问,类外不行
private只有本类内部可以访问,子类也不行!

继承方式会影响父类成员在子类中的访问权限!

父类成员原本是使用 public 继承使用 protected 继承使用 private 继承
public在子类中仍是 public变为 protected变为 private
protected在子类中仍是 protected仍是 protected变为 private
private不可访问(子类也看不到)不可访问不可访问

最佳实践:绝大多数情况下,使用 public 继承!


🧩 四、派生类新增功能 & 重写(override)基类方法

1. 派生类可以新增自己的成员函数和数据

比如:

class Student : public Person {
public:void study() {std::cout << "Student is studying.\n";}
};

2. 派生类可以重写(override)基类的方法

比如,基类有个 speak(),子类想改成自己风格的“说话”:

class Person {
public:virtual void speak() {  // 注意这里用了 virtual(后面会讲)std::cout << "I am a person.\n";}
};class Student : public Person {
public:void speak() override {  // 重写基类的 speakstd::cout << "I am a student!\n";}
};

⚠️ 如果希望允许子类重写,基类方法一般要加 virtual,这样才支持多态(第13章后半部分和第14章重点!)


🧩 五、访问基类的成员(this-> 或 直接调用)

在派生类中,你可以直接访问基类的 public 和 protected 成员

class Person {
protected:int age;
};class Student : public Person {
public:void printAge() {std::cout << "Age is: " << age << std::endl; // 直接访问基类的 protected 成员}
};

如果名字冲突,可以用 Person:: 来显式指明:

Person::someFunction();

🧩 六、继承体系下的构造与析构(重要!)

1. 构造顺序:先基类,后派生类

class Person {
public:Person() { std::cout << "Person()\n"; }
};class Student : public Person {
public:Student() { std::cout << "Student()\n"; }
};// 调用:
Student s; 
// 输出:
// Person()
// Student()

2. 析构顺序:先派生类,后基类(倒过来)

// 析构顺序:
// ~Student()
// ~Person()

3. 如果基类有带参数的构造函数,派生类必须手动调用它:

class Person {
public:Person(std::string n) { std::cout << "Person: " << n << "\n"; }
};class Student : public Person {
public:Student(std::string n) : Person(n) {  // 必须显式调用基类构造std::cout << "Student: " << n << "\n";}
};

🧩 七、继承与多态(为第14章铺路 👣)

虽然第13章主要讲继承基础,但它为下面这个超级重要的概念打下了基础 👇

多态(Polymorphism):让基类指针/引用可以指向不同的子类对象,并调用正确的函数。

关键就是:

  • 基类方法加 virtual

  • 派生类可以重写(override)

  • 通过基类指针或引用调用时,会根据实际对象类型来决定调用谁的版本

我们会在第14章深入,但第13章已经埋下伏笔 ✅


📚 本章小结(超精简版)

主题说明是否重点
继承概念子类继承父类,实现代码复用和功能扩展✅ 核心
继承语法class 派生类 : public 基类✅ 必会
is-a 关系只有“是一个”关系才适合继承✅ 理解本质
访问控制public/protected/private 继承影响基类成员在子类中的可见性✅ 重要细节
成员访问派生类可以直接访问基类的 public/protected 成员✅ 常用
重写方法派生类可以重写基类方法(通常配合 virtual)✅ 多态基础
构造/析构顺序先基类构造,后派生类;析构则相反✅ 重要
多态铺垫为第14章的虚函数和动态绑定打基础✅ 后续重点

🎁 学完这一章,你就能:

  • ✅ 理解什么是继承,为什么要用继承

  • ✅ 会写 class Derived : public Base 这种语法

  • ✅ 知道基类和派生类成员的访问规则

  • ✅ 会正确构造和初始化继承体系中的对象

  • ✅ 为后续学习多态、虚函数、抽象类打下坚实基础


📌 想深入?接下来你可以:

  1. 继续学习第14章:虚函数与多态(超级重要!)

  2. 动手写个小项目:比如游戏角色系统、图形类层次(Shape -> Circle / Square)

  3. 尝试自己设计一个简单的继承体系,比如:动物 -> 狗 / 猫


🔥 总结一句话:

继承让你站在巨人的肩膀上,不用重复造轮子,还能定制自己的超能力!

我们接着深入讲解《C++ Primer》第13章关于类继承(Class Inheritance)的更多细节,尤其是那些你容易忽略但又特别重要的点,还会用更生动的例子、图示和类比帮你彻底掌握!🔥


🧠 一、继承的核心目的回顾(再巩固一下)

继承的本质是:代码复用 + 功能扩展,建立“is-a(是一个)”的层次关系。

你可以把继承想象成一个家族技能树或者公司职位层级

类比说明
家族“程序员”是一个“员工”,程序员继承了员工的基本属性(姓名、工资),还有自己的技能(写代码)
游戏角色“战士”是一个“角色”,继承了角色的基本属性(血量、名字),还有自己的技能(挥剑攻击)
公司“经理”是一个“员工”,继承了员工的基本信息,同时还有管理职能

🏗️ 二、继承体系中的构造与析构(再深入)

这是第13章一个非常关键、面试常考,也是实际开发中容易出错的点 👇


✅ 1. 构造函数的调用顺序:先基类,后派生类

🧩 例子:

#include <iostream>
using namespace std;class Base {
public:Base() { cout << "Base Constructor\n"; }~Base() { cout << "Base Destructor\n"; }
};class Derived : public Base {
public:Derived() { cout << "Derived Constructor\n"; }~Derived() { cout << "Derived Destructor\n"; }
};int main() {Derived d;  // 创建一个派生类对象return 0;
}

🖨️ 输出结果:

Base Constructor   ← 先调用基类构造
Derived Constructor ← 再调用派生类构造
Derived Destructor  ← 析构时,先派生类
Base Destructor     ← 后基类

结论:

  • 构造顺序:基类 → 派生类

  • 析构顺序:派生类 → 基类(倒过来!)

  • 析构顺序很重要,比如基类里开了资源,得等派生类清理完后再收基类的资源!


✅ 2. 如果基类没有默认构造函数,派生类必须手动调用基类构造!

❌ 错误示范:

class Base {
public:Base(int x) { /*...*/ }  // 基类没有默认构造
};class Derived : public Base {
public:Derived() { /*...*/ }  // ❌ 编译错误!不知道怎么构造 Base
};

✅ 正确做法:在派生类构造函数的初始化列表里显式调用基类构造

class Base {
public:Base(int x) { cout << "Base(int): " << x << endl; }
};class Derived : public Base {
public:Derived() : Base(42) {  // ✅ 手动调用基类构造函数cout << "Derived()\n";}
};

🎯 记住:派生类构造时,若基类没有默认构造,必须在初始化列表里显式调用基类的某个构造函数!


🧠 小知识:成员初始化顺序

  • 先按继承顺序初始化基类

  • 再按声明顺序初始化派生类自己的成员变量

  • 最后执行派生类构造函数的函数体


🧩 三、继承与访问控制(再缕一缕)

这是第13章一个容易混淆的点,我们再清晰梳理一遍 👇


1. 基类成员有三种访问级别:

访问级别谁能访问?
public任何地方(对象、子类、函数等)都可以访问
protected只有本类和子类可以访问,外部代码不行
private只有本类内部可以访问,子类和外部都不行

2. 继承方式会影响基类成员在派生类中的访问权限

基类中成员原本是使用 public 继承使用 protected 继承使用 private 继承
public在子类中仍是 public变为 protected变为 private
protected在子类中仍是 protected仍是 protected变为 private
private不可访问(子类也看不见)不可访问不可访问

✅ 最常用:public 继承

表示一种 “是一个(is-a)”关系,并且保持基类接口的开放性。

class Base { public: void foo(); };
class Derived : public Base { };  // ✅ 推荐:foo() 在 Derived 中仍是 public

⚠️ 不推荐:private / protected 继承(特殊用途,一般用组合代替)

  • private 继承:表示“根据基类实现”(is-implemented-in-terms-of),但一般用 成员变量(组合) 更合适

  • protected 继承:几乎不用,了解即可


🧩 四、继承与函数重写(Override)——为多态铺路

1. 什么是重写(Override)?

子类可以重新定义(override)从基类继承来的同名函数,提供自己的实现。

🧩 例子:

class Animal {
public:void speak() { cout << "Animal sound\n"; }
};class Dog : public Animal {
public:void speak() { cout << "Woof!\n"; }  // 重写了基类的 speak
};

但注意:如果基类函数不是 virtual 的,那不叫多态意义上的重写,只是隐藏。


2. 虚函数(virtual)与多态(下章重点,第14章)

如果希望通过基类指针或引用调用到真正子类的函数,就要用到:

virtual 返回类型 函数名(参数);

我们会在第14章深入讲解 虚函数、动态绑定、override关键字、final 等高级特性,第13章是为它打下基础!


🧩 五、继承体系中的名字查找(Name Lookup)

问题:如果子类和基类有同名函数或变量,会发生什么?

👉 C++ 名字查找规则是:先在派生类里找,找到了就停,不再去基类找!

🧩 例子:

class Base {
public:void func() { cout << "Base::func\n"; }
};class Derived : public Base {
public:void func() { cout << "Derived::func\n"; }
};int main() {Derived d;d.func();  // 调用的是 Derived::func
}

输出:

Derived::func

❗ 如果你还想调用基类的版本,可以显式指定:

d.Base::func();  // 明确调用基类版本

🧩 六、继承的经典应用场景(你一定要会!)

场景说明是否推荐用继承
游戏角色系统比如“角色”基类,“战士”、“法师”等继承它✅ 推荐,is-a 关系
图形类层次比如“形状 Shape”基类,“圆形 Circle”、“矩形 Rectangle”继承✅ 推荐,多态绘图
动物类系统“动物”基类,“狗”、“猫”等继承,有不同叫声✅ 推荐
员工系统“员工 Employee”基类,“经理 Manager”、“工程师 Engineer”继承✅ 推荐
汽车与引擎“车”有一个“引擎”,这是 has-a,不该用继承!应该用组合❌ 不推荐,该用成员变量

🧠 判断标准:如果是“是一个”,用继承;如果是“有一个”,用组合(成员变量)!


🎓 七、本章学完你就能掌握什么?(能力清单 ✅)

技能是否掌握
理解继承的基本概念与语法:class Derived : public Base
知道为什么要用继承:代码复用 + 功能扩展
能正确使用 public/protected/private 继承
理解继承后的成员访问权限变化
知道构造函数与析构函数的调用顺序
会手动调用基类构造函数(初始化列表)
理解函数重写(Override)与虚函数基础✅(为第14章铺路)
能区分“is-a”和“has-a”,知道何时用继承、何时用组合
能设计简单的类继承体系(比如图形、动物、角色等)

📌 下一步学什么?强烈推荐 👇

✅ 继续学习第14章:虚函数与多态(Virtual Functions and Polymorphism)

这是 C++ 面向对象编程的核心中的核心!

你将学到:

  • 什么是多态(同一接口,不同行为)

  • 什么是虚函数(virtual function)

  • 什么是动态绑定(运行时决定调用谁)

  • override 和 final 关键字

  • 抽象类与纯虚函数(interface 的雏形)

🎯 继承让类有层次,多态让类有灵魂!


🎁 想进一步动手?可以试试这些小练习:

  1. 设计一个图形类层次:

    • 基类:Shape(有 area() 和 draw())

    • 派生类:Circle、Rectangle、Triangle

    • 用基类指针调用不同子类的 draw()

  2. 设计一个游戏角色系统:

    • 基类:Character(有 name, hp)

    • 派生类:Warrior、Mage、Archer,各有不同技能

  3. 实现一个简单的员工管理系统:

    • 基类:Employee

    • 派生类:Manager、Engineer、Intern


✅ 总结一句话:

继承让你可以基于已有类快速构建新类,既省代码,又有层次,是面向对象设计的基石之一!

继续跟我一起探索 C++ 的面向对象魔法吧! 🚀🎯

 

既然想继续深入、动手实践,那我们就一鼓作气,继续生成更多实用、生动、可运行的内容,帮助你真正掌握 C++ 的类继承(第13章),并自然过渡到多态(第14章)的核心概念


🎯 接下来我们生成什么?

为了学得更爽、更深入、更实战,我们规划了以下几个部分,层层递进,边学边练


🧩 一、动手实践:图形类继承体系(Shape → Circle / Rectangle)

✅ 目标:用继承实现一个简单的图形类层次结构,练习基类与派生类关系、方法重写、多态基础。


🎨 1. 问题描述

我们设计一个图形系统,有如下类:

  • 基类:Shape(形状)

    • 属性:无(或可加名字)

    • 方法:virtual double area() const → 返回面积(虚函数,便于多态)

    • 方法:virtual void draw() const → 打印图形信息(虚函数,用于演示多态)

  • 派生类:Circle(圆形)

    • 属性:半径 radius

    • 重写 area() 和 draw()

  • 派生类:Rectangle(矩形)

    • 属性:宽 width,高 height

    • 重写 area() 和 draw()


🧱 2. 代码实现(可直接复制运行)

#include <iostream>
#include <cmath>
using namespace std;// 基类:Shape
class Shape {
public:virtual ~Shape() {} // 虚析构函数,防止派生类对象通过基类指针删除时资源泄漏// 虚函数:计算面积virtual double area() const {cout << "Shape area (not implemented)" << endl;return 0.0;}// 虚函数:绘制图形(打印信息)virtual void draw() const {cout << "Drawing a generic Shape." << endl;}
};// 派生类:Circle
class Circle : public Shape {
private:double radius;public:Circle(double r) : radius(r) {}double area() const override {return M_PI * radius * radius;}void draw() const override {cout << "Drawing a Circle with radius " << radius<< ", area = " << area() << endl;}
};// 派生类:Rectangle
class Rectangle : public Shape {
private:double width, height;public:Rectangle(double w, double h) : width(w), height(h) {}double area() const override {return width * height;}void draw() const override {cout << "Drawing a Rectangle " << width << "x" << height<< ", area = " << area() << endl;}
};

▶️ 3. 测试代码(main 函数,演示多态)

int main() {// 创建不同图形对象Circle c(5.0);Rectangle r(4.0, 6.0);// 直接调用c.draw();r.draw();cout << "===== 通过基类指针实现多态 =====" << endl;// 基类指针指向派生类对象(多态的关键!)Shape* shapes[] = { &c, &r };for (Shape* s : shapes) {s->draw();    // 动态绑定,调用实际子类版本的 draw()cout << "Area: " << s->area() << endl;  // 动态绑定,调用实际子类 area()cout << "-----------------" << endl;}return 0;
}

🖨️ 4. 输出结果(示例)

Drawing a Circle with radius 5, area = 78.5398
Drawing a Rectangle 4x6, area = 24
===== 通过基类指针实现多态 =====
Drawing a Circle with radius 5, area = 78.5398
Area: 78.5398
-----------------
Drawing a Rectangle 4x6, area = 24
Area: 24
-----------------

这就是多态的雏形! 通过基类指针调用虚函数,实际执行的是派生类自己重写的版本


🧩 二、进阶练习:动物叫声系统(Animal → Dog / Cat)

✅ 目标:练习继承 + 重写 + 多态,模拟不同动物的叫声


🐾 类设计

  • 基类:Animal

    • 方法:virtual void speak() const

  • 派生类:Dog → 重写 speak() 输出 "Woof!"

  • 派生类:Cat → 重写 speak() 输出 "Meow!"


🧱 代码实现

#include <iostream>
using namespace std;// 基类
class Animal {
public:virtual void speak() const {cout << "Animal makes a sound" << endl;}virtual ~Animal() {}
};// 派生类:Dog
class Dog : public Animal {
public:void speak() const override {cout << "Dog says: Woof!" << endl;}
};// 派生类:Cat
class Cat : public Animal {
public:void speak() const override {cout << "Cat says: Meow!" << endl;}
};

▶️ 测试代码

int main() {Animal* animals[] = { new Dog(), new Cat() };for (Animal* a : animals) {a->speak();  // 多态调用delete a;    // 记得释放!基类有虚析构,安全}return 0;
}

🐶🐱 输出结果

Dog says: Woof!
Cat says: Meow!

✅ 你可以看到,虽然我们用的是基类指针 Animal*,但实际调用的却是各自子类重写的 speak() 方法,这就是运行时多态(动态绑定)


🧩 三、继承的最佳实践与常见误区(🎓知识点总结)

知识点说明是否掌握
继承语法class Derived : public Base
public 继承表示“是一个(is-a)”关系,最常用
构造顺序先基类构造,后派生类构造
析构顺序先派生类析构,后基类析构;基类应有虚析构函数
成员访问派生类可以直接访问基类的 public/protected 成员
函数重写派生类重写基类函数,通常要加 override(C++11起)
虚函数与多态基类函数加 virtual,通过基类指针/引用调用实际子类函数✅(第14章深入)
is-a vs has-a只有“是一个”关系才用继承,否则用组合(成员变量)
不要滥用继承继承是强耦合,优先考虑组合,除非真是层次关系

🧠 四、为什么要学这些?——因为你即将进入 C++ OOP 的核心!

后续内容你将学到
第14章:虚函数与多态深入 dynamic binding、override、final、抽象类、纯虚函数
第15章:模板与泛型编程学会写通用代码,比如模板类、模板函数
第16章:面向对象设计模式比如工厂模式、策略模式,很多都基于继承与多态
实际项目开发游戏开发、GUI框架、业务系统都重度依赖继承与多态

✅ 你现在可以自豪地说:

我已经掌握了 C++ 类继承的核心:

  • 我会用 class Derived : public Base 写继承体系

  • 我知道构造和析构顺序

  • 我理解 public/protected/private 继承的区别

  • 我会重写基类函数,为多态打基础

  • 我能设计图形类、动物类等实际案例

  • 我理解 is-a 关系,知道什么时候用继承,什么时候用组合

 

 


✅ 总结一句话:

继承让你可以基于已有类快速构建逻辑相关的类,搭配虚函数与多态,让你的代码更灵活、更强大、更贴近真实世界的建模!


🚀 现在已经站在了 C++ 面向对象编程的核心门槛上,下一步就是掌握多态与虚函数,彻底释放面向对象的威力!

哈哈!咱们来点轻松幽默的,用 C++ 面向对象编程,特别是继承 + 多态,来搞一个 “动物园管理系统”,而且要整得有梗、有料、有趣味,让代码既实用又有娱乐精神!🦁🐼🐘🎪


🎪 项目名称:“疯狂动物园”管理系统(Crazy Zoo Management System)


🐒 一、项目背景(故事情节)

有一天,你穿越到了一个平行世界,成为了“疯狂动物园”的首席程序员兼园长助理

这个动物园里有各种动物,比如:

  • 🦁 狮子(会吼叫)

  • 🐼 熊猫(会卖萌吃竹子)

  • 🐘 大象(会喷水)

  • 🦒 长颈鹿(会吃树叶)

  • 🐧 企鹅(会吐槽天气冷)

你的任务是:用 C++ 面向对象的方式,设计一个“动物管理系统”,让每种动物都能自我介绍、做动作,而且代码还要优雅、可扩展、有幽默感!


🧠 二、设计思路(技术角度,依然严谨)

✅ 你会用到的核心技术:

技术说明幽默翻译
继承(Inheritance)每种动物都是“动物”这个基类的孩子所有动物都说自己是“动物界优秀毕业生”
多态(Polymorphism)不同动物调用相同函数,却做出不同行为同一个指令:“表演一个才艺”,结果狮子吼、熊猫吃、企鹅抖
虚函数(virtual)基类定义“接口”,子类实现“个性”父类说:“来秀一个!”,子类各显神通
纯虚函数 + 抽象类基类定义“必须做的事”,但不做具体实现动物园规定:每个动物都必须会“自我介绍”,但爱咋介绍咋介绍

🏗️ 三、代码实现(幽默版动物园系统)


1️⃣ 第一步:定义基类 —— 动物(Animal)

#include <iostream>
#include <vector>
#include <memory>
using namespace std;// 基类:动物(抽象类,不能直接实例化)
class Animal {
public:// 纯虚函数:自我介绍(每个动物都必须会!不然开除!)virtual void introduce() const = 0;// 纯虚函数:表演才艺(每个动物都得有点本事)virtual void perform() const = 0;// 虚析构函数,防止内存泄漏virtual ~Animal() {// 动物走了,也要优雅地离开舞台}
};

🎭 解说:这个基类就像动物园园规,告诉所有动物:“想进园?先学会自我介绍和表演!”


2️⃣ 第二步:定义各种动物子类(幽默版)


🦁 狮子类(会吼)

class Lion : public Animal {
public:void introduce() const override {cout << "🦁 嗷呜~ 我是森林之王狮子!我的鬃毛比你的发量还多!" << endl;}void perform() const override {cout << "🦁 ROAR!!! (震耳欲聋的狮吼功,游客吓得捂耳朵)" << endl;}
};

🐼 熊猫类(卖萌吃竹子)

class Panda : public Animal {
public:void introduce() const override {cout << "🐼 咕噜~ 我是国宝熊猫,我每天只干三件事:吃、睡、卖萌!" << endl;}void perform() const override {cout << "🐼 啃竹子中... 咔嚓咔嚓,萌翻全场!" << endl;}
};

🐘 大象类(喷水绝技)

class Elephant : public Animal {
public:void introduce() const override {cout << "🐘 嗡~ 我是大象,鼻子长,力气大,还会喷水洗澡!" << endl;}void perform() const override {cout << "🐘 🌊 扭动鼻子,哗—— 一股清泉滋向天空!(游客欢呼)" << endl;}
};

🦒 长颈鹿类(优雅吃树叶)

class Giraffe : public Animal {
public:void introduce() const override {cout << "🦒 哒哒~ 我是长颈鹿,脖子最长,看风景不用排队!" << endl;}void perform() const override {cout << "🦒 🌿 优雅地嚼着树叶,俯视你们这些矮子~" << endl;}
};

🐧 企鹅类(吐槽天气)

class Penguin : public Animal {
public:void introduce() const override {cout << "🐧 哇凉哇凉~ 我是企鹅,生活在南极,你们那叫春天?我叫冬天!" << endl;}void perform() const override {cout << "🐧 🥶 摇晃着走路,‘这破天气,冻得我企鹅都穿羽绒服了!’" << endl;}
};

3️⃣ 第三步:主函数 —— 动物园表演开始!

int main() {cout << "========== 欢迎来到疯狂动物园!==========\n";// 用智能指针管理动物对象(防止内存泄漏,优雅!)vector<unique_ptr<Animal>> animals;// 各路动物入园报道animals.push_back(make_unique<Lion>());animals.push_back(make_unique<Panda>());animals.push_back(make_unique<Elephant>());animals.push_back(make_unique<Giraffe>());animals.push_back(make_unique<Penguin>());// 每个动物上台:先自我介绍,再表演才艺for (const auto& animal : animals) {animal->introduce();  // 自我介绍cout << "---- 接下来表演 ----" << endl;animal->perform();    // 才艺表演cout << "==========================" << endl;}cout << "🎉 感谢观看疯狂动物园的表演,动物们今晚加鸡腿! 🍗" << endl;return 0;
}

🎭 四、运行效果(幽默版输出,脑补画面 😂)

========== 欢迎来到疯狂动物园!==========
🦁 嗷呜~ 我是森林之王狮子!我的鬃毛比你的发量还多!
---- 接下来表演 ----
🦁 ROAR!!! (震耳欲聋的狮吼功,游客吓得捂耳朵)
==========================
🐼 咕噜~ 我是国宝熊猫,我每天只干三件事:吃、睡、卖萌!
---- 接下来表演 ----
🐼 啃竹子中... 咔嚓咔嚓,萌翻全场!
==========================
🐘 嗡~ 我是大象,鼻子长,力气大,还会喷水洗澡!
---- 接下来表演 ----
🐘 🌊 扭动鼻子,哗—— 一股清泉滋向天空!(游客欢呼)
==========================
🦒 哒哒~ 我是长颈鹿,脖子最长,看风景不用排队!
---- 接下来表演 ----
🦒 🌿 优雅地嚼着树叶,俯视你们这些矮子~
==========================
🐧 哇凉哇凉~ 我是企鹅,生活在南极,你们那叫春天?我叫冬天!
---- 接下来表演 ----
🐧 🥶 摇晃着走路,‘这破天气,冻得我企鹅都穿羽绒服了!’
==========================
🎉 感谢观看疯狂动物园的表演,动物们今晚加鸡腿! 🍗

🧠 五、你学到了什么?(技术 + 幽默双丰收)

技术点你做到了啥幽默解读
继承所有动物都继承自 Animal 基类所有动物都持证上岗,都是“动物界公务员”
多态同样的 introduce() 和 perform(),不同动物不同表现同一个舞台,不同的秀,这才是动物园的魅力
纯虚函数 + 抽象类Animal 是抽象类,不能直接创建对象园长说了:想混动物园?先学会自我介绍和表演!
override每个子类都重写了虚函数每个动物都交出了自己的“绝活”作业
智能指针用 unique_ptr 管理动物对象,避免内存泄漏动物园讲究环保,连代码都绿色!

🎁 六、Bonus:如何扩展这个系统?(脑洞时间 😎)

想法实现思路
🦓 加个斑马?派生个 Zebra 类,自我介绍:“我是黑白条纹控!”
🐒 加个猴哥?派生 Monkey 类,表演:“模仿游客拍照!”
🎤 动物园主持人?单独搞个 Host 类,负责串场:“下面有请下一位动物明星!”
📅 按时间表表演?用 map 或 vector 按时间调度动物表演
🏆 最佳表演奖?加个评分系统,游客可以打分,年底颁奖!

✅ 总结一句话:

继承让动物们成为“一家人”,多态让它们个个是“戏精”,而 C++ 让这场疯狂动物园秀,既优雅又搞笑!


🚀 下一步挑战(如果你意犹未尽)

  • 为动物添加 年龄、名字属性

  • 让游客可以选择想看的动物

  • 做个简单的菜单系统(控制台交互)

  • 文件存储 动物信息,实现存档功能

  • 把它做成带图形界面(Qt / GUI)的动物园游戏


🎉 


 

http://www.dtcms.com/a/516479.html

相关文章:

  • “VMware与vmx86驱动程序版本不匹配:预期为:417,实际为416。”解决步骤,亲测有效!!!
  • 查找组成一个偶数最接近的两个素数
  • 获取文件版本(C++源码)
  • 济南网站建设鲁icp备附近展览制作工厂
  • 在Windows WSL2中安装Ubuntu和Docker的完整指南
  • Ubuntu 22 .04安装CUDA, cuDNN, TensorRT
  • Linux编辑神器——vim工具的使用
  • UPS-不间断电源系统
  • AMDGPU/KFD IV(Interrupt Vector)信息结构及实现
  • 网站开发公司计划书如何做英文网站的外链
  • 彬县网站建设it外包前景
  • 网站集约化做暧暧国外网站
  • 基于python的电子商务管理系统
  • Git Remote 实现双向仓库同步教程(适合跨公司协作)
  • 检测网站开发语言工具wordpress免回复
  • 【python】Pillow 快速入门
  • [特殊字符] [特殊字符][特殊字符]这样的 ​Emoji 表情符号​ 是怎么来的、怎么显示出来的,以及它们到底是怎么工作的
  • Salesforce Connected App 创建指南
  • 做的比较好的国外网站一级页面布局分析海外短视频服务器
  • 42.接雨水
  • 衡水网站建设地方网页界面设计案例分析
  • Process Monitor 学习笔记(5.24):工具栏参考与高效快捷键指南
  • UE5 材质-15:车漆-不透明-透明图层,FBX格式的介绍,如何导入外部模型FBX汽车,下载与使用官方的汽车材质 automotive materials,
  • qt实用学习案例:数据库设计+图表显示+model-view模式+样式表定制
  • 脉冲神经网络最新文献合集-XX
  • wordpress做学校网站thinkphp 网站源码
  • 数据库(6)
  • 【性能优化】--perfetto分析思路
  • **发散创新:探索生物神经网络与编程语言的交融**随着生物神经网络研
  • 平台网站开发公司广州安全教育平台登陆