【C++基础与提高】第十一章:面向对象编程进阶——继承与多态

【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 = &rect;
    std::cout << "矩形面积: " << shape_ptr->area() << std::endl;  // 多态调用
    
    shape_ptr = &circle;
    std::cout << "圆形面积: " << shape_ptr->area() << std::endl;  // 多态调用
    
    shape_ptr = &triangle;
    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++面向对象编程的核心概念:

  1. 继承基础:公有、保护、私有继承的区别和应用
  2. 虚函数与多态:运行时多态的实现机制
  3. 虚函数表:动态绑定的底层实现原理
  4. 抽象类与接口:定义契约和强制实现
  5. 构造与析构顺序:继承层次中的对象生命周期管理
  6. 虚继承:解决菱形继承问题

继承和多态是C++面向对象编程的基石,它们提供了代码复用、接口抽象和运行时多态的强大能力。正确理解和运用这些概念对于设计灵活、可扩展的软件系统至关重要。

通过本章的学习,你应该能够:

  • 设计合理的继承层次结构
  • 正确使用虚函数实现多态
  • 理解虚函数表的工作原理
  • 运用抽象类定义接口契约
  • 掌握复杂的继承关系处理

这些知识为后续学习模板、STL和现代C++特性奠定了坚实基础。

相关推荐
艾莉丝努力练剑1 小时前
【C++:封装红黑树】C++红黑树封装实战:从零实现MyMap与MySet
c++·stl·set·map·红黑树·平衡二叉树
aerror1 小时前
将sqlite3的表转成excel表
java·sqlite·excel
仟濹1 小时前
IntelliJ IDEA 快捷键 + 实时模板
java·intellij-idea
洛_尘1 小时前
数据结构--6:优先级队列(堆)
java·数据结构
四维碎片1 小时前
【Qt】多线程学习笔记
笔记·qt·学习
序属秋秋秋1 小时前
《Linux系统编程之进程基础》【进程入门】
linux·运维·c语言·c++·进程·系统编程·fork
大飞哥~BigFei1 小时前
RabbitMq消费消息遇到的坑
java·rabbitmq·java-rabbitmq
点云SLAM2 小时前
Boost库中Boost.PropertyTree使用和实战示例
开发语言·c++·josn·boost库·参数读取