【C++基础与提高】第十一章:面向对象编程进阶------继承与多态
(持续更新中,欢迎关注!)
文章目录
- 【C++基础与提高】第十一章:面向对象编程进阶------继承与多态
-
-
- [11.1 继承基础------代码复用的利器](#11.1 继承基础——代码复用的利器)
- [11.2 继承方式详解------不同的访问控制](#11.2 继承方式详解——不同的访问控制)
- [11.3 虚函数与多态------运行时多态的实现](#11.3 虚函数与多态——运行时多态的实现)
- [11.4 虚函数表与动态绑定------多态的底层机制](#11.4 虚函数表与动态绑定——多态的底层机制)
- [11.5 抽象类与接口------定义契约](#11.5 抽象类与接口——定义契约)
- [11.6 继承中的构造与析构顺序](#11.6 继承中的构造与析构顺序)
- [11.7 本章小结](#11.7 本章小结)
-
11.1 继承基础------代码复用的利器
继承是面向对象编程的核心特性之一,它允许我们基于现有类创建新类,从而实现代码复用和层次化设计。
cpp
#include <iostream>
#include <string>
// 1. 基类(父类)
class Vehicle {
protected: // 保护成员,派生类可以访问
std::string brand;
int year;
double price;
public:
Vehicle(const std::string& b, int y, double p)
: brand(b), year(y), price(p) {
std::cout << "Vehicle构造函数被调用" << std::endl;
}
virtual ~Vehicle() {
std::cout << "Vehicle析构函数被调用" << std::endl;
}
// 公有成员函数
void display_info() const {
std::cout << "品牌: " << brand << ", 年份: " << year
<< ", 价格: " << price << std::endl;
}
// 虚函数,支持多态
virtual void start() const {
std::cout << brand << " 车辆启动" << std::endl;
}
virtual double calculate_insurance() const {
return price * 0.05; // 基础保险费率
}
// 访问器函数
std::string get_brand() const { return brand; }
int get_year() const { return year; }
double get_price() const { return price; }
};
// 2. 派生类(子类)- 公有继承
class Car : public Vehicle {
private:
int doors;
std::string fuel_type;
public:
Car(const std::string& brand, int year, double price,
int d, const std::string& fuel)
: Vehicle(brand, year, price), doors(d), fuel_type(fuel) {
std::cout << "Car构造函数被调用" << std::endl;
}
~Car() {
std::cout << "Car析构函数被调用" << std::endl;
}
// 重写基类的虚函数
void start() const override {
std::cout << brand << " 汽车启动," << doors << "门" << std::endl;
}
double calculate_insurance() const override {
double base_insurance = Vehicle::calculate_insurance();
// 汽车可能有更高的保险费率
return base_insurance * 1.2;
}
// 派生类特有的函数
void honk() const {
std::cout << brand << " 汽车鸣笛: 嘀嘀!" << std::endl;
}
void display_car_info() const {
display_info(); // 调用基类函数
std::cout << "门数: " << doors << ", 燃料类型: " << fuel_type << std::endl;
}
};
// 3. 另一个派生类
class Motorcycle : public Vehicle {
private:
int engine_cc;
bool has_sidecar;
public:
Motorcycle(const std::string& brand, int year, double price,
int cc, bool sidecar)
: Vehicle(brand, year, price), engine_cc(cc), has_sidecar(sidecar) {
std::cout << "Motorcycle构造函数被调用" << std::endl;
}
~Motorcycle() {
std::cout << "Motorcycle析构函数被调用" << std::endl;
}
// 重写基类的虚函数
void start() const override {
std::cout << brand << " 摩托车启动," << engine_cc << "cc引擎" << std::endl;
}
double calculate_insurance() const override {
double base_insurance = Vehicle::calculate_insurance();
// 摩托车保险费率可能不同
double cc_factor = (engine_cc > 250) ? 1.5 : 1.0;
double sidecar_factor = has_sidecar ? 1.3 : 1.0;
return base_insurance * cc_factor * sidecar_factor;
}
void wheelie() const {
std::cout << brand << " 摩托车后轮着地!" << std::endl;
}
};
int main() {
std::cout << "=== 继承演示 ===" << std::endl;
// 1. 创建派生类对象
{
Car my_car("丰田", 2020, 200000, 4, "汽油");
std::cout << "\n汽车信息:" << std::endl;
my_car.display_car_info();
my_car.start();
my_car.honk();
std::cout << "汽车保险费: " << my_car.calculate_insurance() << std::endl;
std::cout << "\n摩托车信息:" << std::endl;
Motorcycle my_motorcycle("本田", 2021, 80000, 150, false);
my_motorcycle.display_info();
my_motorcycle.start();
my_motorcycle.wheelie();
std::cout << "摩托车保险费: " << my_motorcycle.calculate_insurance() << std::endl;
}
return 0;
}
11.2 继承方式详解------不同的访问控制
cpp
#include <iostream>
#include <string>
// 基类
class Base {
public:
int public_member = 1;
protected:
int protected_member = 2;
private:
int private_member = 3;
public:
void base_function() {
std::cout << "基类函数访问成员:" << std::endl;
std::cout << " public_member: " << public_member << std::endl;
std::cout << " protected_member: " << protected_member << std::endl;
std::cout << " private_member: " << private_member << std::endl;
}
};
// 公有继承
class PublicDerived : public Base {
public:
void derived_function() {
std::cout << "公有派生类访问成员:" << std::endl;
std::cout << " public_member: " << public_member << std::endl; // 可访问
std::cout << " protected_member: " << protected_member << std::endl; // 可访问
// std::cout << " private_member: " << private_member << std::endl; // 不可访问
}
};
// 保护继承
class ProtectedDerived : protected Base {
public:
void derived_function() {
std::cout << "保护派生类访问成员:" << std::endl;
std::cout << " public_member: " << public_member << std::endl; // 可访问(变为protected)
std::cout << " protected_member: " << protected_member << std::endl; // 可访问(仍为protected)
}
};
// 私有继承
class PrivateDerived : private Base {
public:
void derived_function() {
std::cout << "私有派生类访问成员:" << std::endl;
std::cout << " public_member: " << public_member << std::endl; // 可访问(变为private)
std::cout << " protected_member: " << protected_member << std::endl; // 可访问(变为private)
}
};
int main() {
std::cout << "=== 继承方式演示 ===" << std::endl;
// 1. 公有继承
PublicDerived pub_obj;
pub_obj.base_function();
pub_obj.derived_function();
std::cout << "外部访问公有派生类:" << std::endl;
std::cout << " public_member: " << pub_obj.public_member << std::endl; // 可访问
// std::cout << " protected_member: " << pub_obj.protected_member << std::endl; // 不可访问
// 2. 保护继承
ProtectedDerived prot_obj;
prot_obj.derived_function();
std::cout << "外部访问保护派生类:" << std::endl;
// std::cout << " public_member: " << prot_obj.public_member << std::endl; // 不可访问(变为protected)
// 3. 私有继承
PrivateDerived priv_obj;
priv_obj.derived_function();
std::cout << "外部访问私有派生类:" << std::endl;
// std::cout << " public_member: " << priv_obj.public_member << std::endl; // 不可访问(变为private)
return 0;
}
11.3 虚函数与多态------运行时多态的实现
cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 1. 抽象基类
class Shape {
protected:
std::string name;
public:
Shape(const std::string& n) : name(n) {}
virtual ~Shape() = default; // 虚析构函数
// 纯虚函数,使类成为抽象类
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual void display() const {
std::cout << "形状: " << name << std::endl;
}
};
// 2. 派生类实现
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : Shape("矩形"), width(w), height(h) {}
double area() const override {
return width * height;
}
double perimeter() const override {
return 2 * (width + height);
}
void display() const override {
Shape::display();
std::cout << " 宽: " << width << ", 高: " << height << std::endl;
std::cout << " 面积: " << area() << ", 周长: " << perimeter() << std::endl;
}
};
class Circle : public Shape {
private:
double radius;
static constexpr double PI = 3.14159265359;
public:
Circle(double r) : Shape("圆形"), radius(r) {}
double area() const override {
return PI * radius * radius;
}
double perimeter() const override {
return 2 * PI * radius;
}
void display() const override {
Shape::display();
std::cout << " 半径: " << radius << std::endl;
std::cout << " 面积: " << area() << ", 周长: " << perimeter() << std::endl;
}
};
class Triangle : public Shape {
private:
double side1, side2, side3;
public:
Triangle(double a, double b, double c) : Shape("三角形"), side1(a), side2(b), side3(c) {}
double area() const override {
// 海伦公式
double s = (side1 + side2 + side3) / 2;
return sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
double perimeter() const override {
return side1 + side2 + side3;
}
void display() const override {
Shape::display();
std::cout << " 三边: " << side1 << ", " << side2 << ", " << side3 << std::endl;
std::cout << " 面积: " << area() << ", 周长: " << perimeter() << std::endl;
}
};
// 3. 多态函数
void print_shape_info(const Shape& shape) {
shape.display(); // 多态调用
std::cout << "------------------------" << std::endl;
}
double calculate_total_area(const std::vector<std::unique_ptr<Shape>>& shapes) {
double total = 0;
for(const auto& shape : shapes) {
total += shape->area(); // 多态调用
}
return total;
}
int main() {
std::cout << "=== 多态演示 ===" << std::endl;
// 1. 多态对象创建
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Rectangle>(5.0, 3.0));
shapes.push_back(std::make_unique<Circle>(4.0));
shapes.push_back(std::make_unique<Triangle>(3.0, 4.0, 5.0));
// 2. 多态调用
std::cout << "形状信息:" << std::endl;
for(const auto& shape : shapes) {
print_shape_info(*shape); // 多态调用display()
}
// 3. 多态计算
std::cout << "总面积: " << calculate_total_area(shapes) << std::endl;
// 4. 直接多态调用
std::cout << "\n直接调用演示:" << std::endl;
Shape* shape_ptr = nullptr;
Rectangle rect(6.0, 4.0);
Circle circle(3.0);
Triangle triangle(5.0, 5.0, 5.0);
shape_ptr = ▭
std::cout << "矩形面积: " << shape_ptr->area() << std::endl; // 多态调用
shape_ptr = &circle;
std::cout << "圆形面积: " << shape_ptr->area() << std::endl; // 多态调用
shape_ptr = ▵
std::cout << "三角形面积: " << shape_ptr->area() << std::endl; // 多态调用
return 0;
}
11.4 虚函数表与动态绑定------多态的底层机制
cpp
#include <iostream>
#include <string>
class Base {
public:
virtual void virtual_function1() {
std::cout << "Base::virtual_function1()" << std::endl;
}
virtual void virtual_function2() {
std::cout << "Base::virtual_function2()" << std::endl;
}
void non_virtual_function() {
std::cout << "Base::non_virtual_function()" << std::endl;
}
virtual ~Base() = default;
};
class Derived : public Base {
public:
void virtual_function1() override {
std::cout << "Derived::virtual_function1()" << std::endl;
}
void virtual_function2() override {
std::cout << "Derived::virtual_function2()" << std::endl;
}
void non_virtual_function() {
std::cout << "Derived::non_virtual_function()" << std::endl;
}
virtual void derived_specific_function() {
std::cout << "Derived::derived_specific_function()" << std::endl;
}
};
class MoreDerived : public Derived {
public:
void virtual_function1() override {
std::cout << "MoreDerived::virtual_function1()" << std::endl;
}
void derived_specific_function() override {
std::cout << "MoreDerived::derived_specific_function()" << std::endl;
}
};
int main() {
std::cout << "=== 虚函数表与动态绑定演示 ===" << std::endl;
// 1. 基类指针指向派生类对象
Base* base_ptr = nullptr;
Derived derived_obj;
MoreDerived more_derived_obj;
std::cout << "=== 基类指针指向派生类对象 ===" << std::endl;
base_ptr = &derived_obj;
base_ptr->virtual_function1(); // 动态绑定,调用Derived版本
base_ptr->virtual_function2(); // 动态绑定,调用Derived版本
base_ptr->non_virtual_function(); // 静态绑定,调用Base版本
std::cout << "\n=== 基类指针指向更深层派生类对象 ===" << std::endl;
base_ptr = &more_derived_obj;
base_ptr->virtual_function1(); // 动态绑定,调用MoreDerived版本
base_ptr->virtual_function2(); // 动态绑定,调用Base版本(未重写)
base_ptr->non_virtual_function(); // 静态绑定,调用Base版本
// 2. 派生类指针的调用
std::cout << "\n=== 派生类指针调用 ===" << std::endl;
Derived* derived_ptr = &derived_obj;
derived_ptr->virtual_function1(); // 动态绑定
derived_ptr->derived_specific_function(); // 直接调用
// 3. 对象直接调用
std::cout << "\n=== 对象直接调用 ===" << std::endl;
derived_obj.virtual_function1(); // 动态绑定(通过对象的虚函数表)
derived_obj.non_virtual_function(); // 直接调用
// 4. 多态数组
std::cout << "\n=== 多态数组演示 ===" << std::endl;
Base* objects[] = {&derived_obj, &more_derived_obj};
for(int i = 0; i < 2; ++i) {
std::cout << "对象 " << (i + 1) << ":" << std::endl;
objects[i]->virtual_function1(); // 多态调用
objects[i]->virtual_function2(); // 多态调用
}
return 0;
}
11.5 抽象类与接口------定义契约
cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 1. 抽象基类 - 定义接口契约
class Drawable {
public:
virtual ~Drawable() = default;
virtual void draw() const = 0; // 纯虚函数
virtual void move(double dx, double dy) = 0;
virtual double get_x() const = 0;
virtual double get_y() const = 0;
};
// 2. 另一个抽象基类
class Resizable {
public:
virtual ~Resizable() = default;
virtual void resize(double factor) = 0;
virtual double get_area() const = 0;
};
// 3. 具体实现类
class Circle : public Drawable, public Resizable {
private:
double x, y; // 位置
double radius; // 半径
static constexpr double PI = 3.14159265359;
public:
Circle(double x_pos, double y_pos, double r)
: x(x_pos), y(y_pos), radius(r) {}
// 实现Drawable接口
void draw() const override {
std::cout << "绘制圆形,中心(" << x << ", " << y
<< "),半径" << radius << std::endl;
}
void move(double dx, double dy) override {
x += dx;
y += dy;
}
double get_x() const override { return x; }
double get_y() const override { return y; }
// 实现Resizable接口
void resize(double factor) override {
radius *= factor;
}
double get_area() const override {
return PI * radius * radius;
}
};
class Rectangle : public Drawable, public Resizable {
private:
double x, y; // 左上角位置
double width, height;
public:
Rectangle(double x_pos, double y_pos, double w, double h)
: x(x_pos), y(y_pos), width(w), height(h) {}
// 实现Drawable接口
void draw() const override {
std::cout << "绘制矩形,左上角(" << x << ", " << y
<< "),宽" << width << ",高" << height << std::endl;
}
void move(double dx, double dy) override {
x += dx;
y += dy;
}
double get_x() const override { return x; }
double get_y() const override { return y; }
// 实现Resizable接口
void resize(double factor) override {
width *= factor;
height *= factor;
}
double get_area() const override {
return width * height;
}
};
// 4. 使用抽象接口的函数
void render_shape(const Drawable& shape) {
shape.draw(); // 多态调用
}
void animate_shape(Drawable& shape) {
std::cout << "动画前位置: (" << shape.get_x() << ", " << shape.get_y() << ")" << std::endl;
shape.move(10, 5);
std::cout << "动画后位置: (" << shape.get_x() << ", " << shape.get_y() << ")" << std::endl;
}
void scale_shape(Resizable& shape, double factor) {
double old_area = shape.get_area();
shape.resize(factor);
double new_area = shape.get_area();
std::cout << "缩放前面积: " << old_area << ",缩放后面积: " << new_area << std::endl;
}
int main() {
std::cout << "=== 抽象类与接口演示 ===" << std::endl;
// 1. 创建具体对象
Circle circle(100, 200, 50);
Rectangle rectangle(50, 75, 100, 80);
// 2. 通过Drawable接口使用
std::cout << "=== 通过Drawable接口 ===" << std::endl;
render_shape(circle);
render_shape(rectangle);
std::cout << "\n=== 动画演示 ===" << std::endl;
animate_shape(circle);
animate_shape(rectangle);
// 3. 通过Resizable接口使用
std::cout << "\n=== 通过Resizable接口 ===" << std::endl;
scale_shape(circle, 2.0);
scale_shape(rectangle, 1.5);
// 4. 多态容器
std::cout << "\n=== 多态容器演示 ===" << std::endl;
std::vector<std::unique_ptr<Drawable>> drawable_objects;
drawable_objects.push_back(std::make_unique<Circle>(0, 0, 30));
drawable_objects.push_back(std::make_unique<Rectangle>(10, 20, 60, 40));
for(const auto& obj : drawable_objects) {
obj->draw();
obj->move(5, 5);
std::cout << "移动后位置: (" << obj->get_x() << ", " << obj->get_y() << ")" << std::endl;
std::cout << "------------------------" << std::endl;
}
return 0;
}
11.6 继承中的构造与析构顺序
cpp
#include <iostream>
#include <string>
// 1. 基类
class Base {
protected:
std::string name;
public:
Base(const std::string& n) : name(n) {
std::cout << "Base构造函数: " << name << std::endl;
}
virtual ~Base() {
std::cout << "Base析构函数: " << name << std::endl;
}
virtual void show() const {
std::cout << "Base: " << name << std::endl;
}
};
// 2. 中间派生类
class Middle : public Base {
private:
int value;
public:
Middle(const std::string& n, int v) : Base(n + "_middle"), value(v) {
std::cout << "Middle构造函数: " << name << ", value=" << value << std::endl;
}
~Middle() {
std::cout << "Middle析构函数: " << name << ", value=" << value << std::endl;
}
void show() const override {
Base::show();
std::cout << "Middle: value=" << value << std::endl;
}
};
// 3. 最终派生类
class Derived : public Middle {
private:
double data;
public:
Derived(const std::string& n, int v, double d)
: Middle(n + "_derived", v), data(d) {
std::cout << "Derived构造函数: " << name << ", data=" << data << std::endl;
}
~Derived() {
std::cout << "Derived析构函数: " << name << ", data=" << data << std::endl;
}
void show() const override {
Middle::show();
std::cout << "Derived: data=" << data << std::endl;
}
};
// 4. 虚继承示例
class Animal {
protected:
std::string species;
public:
Animal(const std::string& s) : species(s) {
std::cout << "Animal构造: " << species << std::endl;
}
virtual ~Animal() {
std::cout << "Animal析构: " << species << std::endl;
}
};
class Mammal : virtual public Animal {
protected:
bool has_fur;
public:
Mammal(const std::string& s, bool fur) : Animal(s), has_fur(fur) {
std::cout << "Mammal构造: " << species << ", fur=" << has_fur << std::endl;
}
~Mammal() {
std::cout << "Mammal析构: " << species << ", fur=" << has_fur << std::endl;
}
};
class Aquatic : virtual public Animal {
protected:
bool can_swim;
public:
Aquatic(const std::string& s, bool swim) : Animal(s), can_swim(swim) {
std::cout << "Aquatic构造: " << species << ", swim=" << can_swim << std::endl;
}
~Aquatic() {
std::cout << "Aquatic析构: " << species << ", swim=" << can_swim << std::endl;
}
};
class Dolphin : public Mammal, public Aquatic {
private:
int intelligence;
public:
Dolphin(const std::string& name, int iq)
: Animal(name), Mammal(name, true), Aquatic(name, true), intelligence(iq) {
std::cout << "Dolphin构造: " << species << ", intelligence=" << intelligence << std::endl;
}
~Dolphin() {
std::cout << "Dolphin析构: " << species << ", intelligence=" << intelligence << std::endl;
}
};
int main() {
std::cout << "=== 构造与析构顺序演示 ===" << std::endl;
{
std::cout << "\n--- 普通继承构造顺序 ---" << std::endl;
Derived obj("test", 42, 3.14);
std::cout << "\n--- 对象使用 ---" << std::endl;
obj.show();
std::cout << "\n--- 析构顺序 ---" << std::endl;
} // 对象作用域结束,开始析构
std::cout << "\n=== 虚继承演示 ===" << std::endl;
{
std::cout << "\n--- 虚继承构造顺序 ---" << std::endl;
Dolphin dolphin("海豚", 95);
std::cout << "\n--- 虚继承析构顺序 ---" << std::endl;
}
return 0;
}
11.7 本章小结
本章深入探讨了C++面向对象编程的核心概念:
- 继承基础:公有、保护、私有继承的区别和应用
- 虚函数与多态:运行时多态的实现机制
- 虚函数表:动态绑定的底层实现原理
- 抽象类与接口:定义契约和强制实现
- 构造与析构顺序:继承层次中的对象生命周期管理
- 虚继承:解决菱形继承问题
继承和多态是C++面向对象编程的基石,它们提供了代码复用、接口抽象和运行时多态的强大能力。正确理解和运用这些概念对于设计灵活、可扩展的软件系统至关重要。
通过本章的学习,你应该能够:
- 设计合理的继承层次结构
- 正确使用虚函数实现多态
- 理解虚函数表的工作原理
- 运用抽象类定义接口契约
- 掌握复杂的继承关系处理
这些知识为后续学习模板、STL和现代C++特性奠定了坚实基础。