C++中动态多态类别浅析

非抽象类继承和虚函数

cpp 复制代码
#include <iostream>
using namespace std;

class Base {
public:
    virtual void func() { // 虚函数,支持动态绑定
        cout << "Base::func()" << endl;
    }
};

class Derived : public Base {
public:
    void func() override { // 重写虚函数
        cout << "Derived::func()" << endl;
    }
};

void call_by_pointer(Base* ptr) {
    ptr->func(); // 动态多态:通过基类指针调用虚函数,实际调用派生类函数
}

void call_by_reference(Base& ref) {
    ref.func(); // 动态多态:通过基类引用调用虚函数,实际调用派生类函数
}

int main() {
    Derived d_obj;
    Base b_obj;

    cout << "--- 1. 通过对象直接调用 ---" << endl;
    d_obj.func(); // 非动态多态:对象类型是 Derived,编译期已决定调用 Derived::func()
    b_obj.func(); // 非动态多态:对象类型是 Base,编译期决定调用 Base::func()

    cout << "--- 2. 通过基类指针指向派生类对象 ---" << endl;
    Base* b_ptr = &d_obj;
    b_ptr->func(); // 动态多态:基类指针指向派生类对象,调用 Derived::func()

    cout << "--- 3. 通过基类引用指向派生类对象 ---" << endl;
    Base& b_ref = d_obj;
    b_ref.func(); // 动态多态:基类引用指向派生类对象,调用 Derived::func()

    cout << "--- 4. 通过函数传参:指针方式 ---" << endl;
    call_by_pointer(&d_obj); // 动态多态

    cout << "--- 5. 通过函数传参:引用方式 ---" << endl;
    call_by_reference(d_obj); // 动态多态

    cout << "--- 6. new 派生类对象赋值给基类指针 ---" << endl;
    Base* heap_ptr = new Derived();
    heap_ptr->func(); // 动态多态
    delete heap_ptr;

    cout << "--- 7. 对象切片(slicing) ---" << endl;
    Base sliced = d_obj; // 非动态多态:对象切片,Derived 部分被切掉
    sliced.func();       // 调用的是 Base::func()

    cout << "--- 8. 基类对象指向派生类地址(强转) ---" << endl;
    Base* forced_ptr = (Base*)&d_obj;
    forced_ptr->func(); // 动态多态:虽然是强转,但对象真实类型仍是 Derived

    return 0;
}

抽象基类 + 纯虚函数(接口模式)

cpp 复制代码
#include <iostream>
#include <vector>
#include <memory>
using namespace std;

// 抽象基类 Shape,定义接口
class Shape {
public:
    virtual double area() const = 0;   // 纯虚函数
    virtual ~Shape() = default;        // 虚析构,保证多态删除安全
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() const override { return 3.14159 * radius * radius; }
};

class Rectangle : public Shape {
    double w, h;
public:
    Rectangle(double w_, double h_) : w(w_), h(h_) {}
    double area() const override { return w * h; }
};

void printArea(const Shape& s) {
    // ✅ 动态多态:通过基类引用调用纯虚函数
    cout << "Area = " << s.area() << endl;
}

int main() {
    vector<unique_ptr<Shape>> shapes;
    shapes.emplace_back(make_unique<Circle>(2.0));
    shapes.emplace_back(make_unique<Rectangle>(3.0, 4.0));

    for (auto& shp : shapes) {
        printArea(*shp);
    }
    return 0;
}
// 场景:用纯虚函数定义接口,派生类实现具体算法。
// 动态多态点:printArea(*shp) 内部的 s.area()

返回类型

cpp 复制代码
#include <iostream>
using namespace std;

// 原型接口
class Prototype {
public:
    virtual Prototype* clone() const = 0;  // 纯虚
    virtual void show() const = 0;
    virtual ~Prototype() = default;
};

class ConcreteA : public Prototype {
    int data;
public:
    ConcreteA(int d) : data(d) {}
    // 协变返回:派生类返回自身类型指针
    ConcreteA* clone() const override { 
        return new ConcreteA(*this); 
    }
    void show() const { cout << "ConcreteA: " << data << endl; }
};

int main() {
    Prototype* p1 = new ConcreteA(42);
    Prototype* p2 = p1->clone();   // 动态多态:clone() 调用派生实现
    p2->show();
    delete p1;
    delete p2;
    return 0;
}
// 场景:通过原型克隆对象,每个具体类返回其自身类型指针。
// 动态多态点:p1->clone()。

多接口继承抽象类

cpp 复制代码
#include <iostream>
using namespace std;

class Printable {
public:
    virtual void print() const = 0;
    virtual ~Printable() = default;
};

class Drawable {
public:
    virtual void draw() const = 0;
    virtual ~Drawable() = default;
};

class Widget : public Printable, public Drawable {
public:
    void print() const override { cout << "Widget::print()\n"; }
    void draw()  const override { cout << "Widget::draw()\n";  }
};

int main() {
    Widget w;
    Printable* p = &w;
    Drawable* d = &w;

    p->print();   // 动态多态:调用 Widget::print()
    d->draw();    // 动态多态:调用 Widget::draw()
    return 0;
}
// 场景:组件同时具备"可打印"和"可绘制"能力,用两个接口分离职责。
// 动态多态点:通过不同基类指针调用对应虚函数。

运行时类型识别(RTTI)+ dynamic_cast

cpp 复制代码
#include <iostream>
using namespace std;

class Base {
public:
    virtual ~Base() = default;
};

class Derived : public Base {
public:
    void special() { cout << "Derived::special()\n"; }
};

void trySpecial(Base* b) {
    // 动态多态 & RTTI:运行时检查实际类型
    if (auto* d = dynamic_cast<Derived*>(b)) {
        d->special();
    } else {
        cout << "Not a Derived\n";
    }
}

int main() {
    Base* b1 = new Base;
    Base* b2 = new Derived;
    trySpecial(b1); // 输出 "Not a Derived"
    trySpecial(b2); // 输出 "Derived::special()"
    delete b1;
    delete b2;
    return 0;
}
// 场景:当你只持有基类指针,但有时需要访问派生类的独有方法。
// 动态多态点:dynamic_cast 根据实际类型成功或失败。

插件式架构(Factory + 多态)

cpp 复制代码
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;

class Plugin {
public:
    virtual void run() = 0;
    virtual ~Plugin() = default;
};

class PluginA : public Plugin {
public:
    void run() override { cout << "PluginA running\n"; }
};
class PluginB : public Plugin {
public:
    void run() override { cout << "PluginB running\n"; }
};

// 简单工厂注册表
map<string, function<Plugin*()>> factoryMap;

void registerPlugin(const string& name, function<Plugin*()> ctor) {
    factoryMap[name] = ctor;
}

Plugin* createPlugin(const string& name) {
    auto it = factoryMap.find(name);
    return it != factoryMap.end() ? it->second() : nullptr;
}

int main() {
    // 注册
    registerPlugin("A", [](){ return new PluginA; });
    registerPlugin("B", [](){ return new PluginB; });

    // 客户端只知道名字,工厂返回多态基类
    Plugin* p = createPlugin("A");
    if (p) p->run();  // ? 动态多态:调用 PluginB::run()
    delete p;
    return 0;
}

// 场景:插件或驱动加载,客户端通过字符串、配置决定用哪个实现。
// 动态多态点:p->run()。
相关推荐
愚润求学22 分钟前
【数据结构】红黑树
数据结构·c++·笔记
Hello eveybody2 小时前
C++按位与(&)、按位或(|)和按位异或(^)
开发语言·c++
被AI抢饭碗的人2 小时前
c++:c++中的输入输出(二)
开发语言·c++
lqqjuly2 小时前
C++ 面向对象关键语法详解:override、虚函数、转发调用和数组引用传参-策略模式
开发语言·c++
EstrangedZ2 小时前
vcpkg缓存问题研究
c语言·c++·缓存·cmake·vcpkg
周Echo周2 小时前
16、堆基础知识点和priority_queue的模拟实现
java·linux·c语言·开发语言·c++·后端·算法
SuperCandyXu3 小时前
leetcode0113. 路径总和 II - medium
数据结构·c++·算法·leetcode
可乐拌面3 小时前
string的模拟实现 (6)
c++·stl
李boyang4 小时前
C++ IO流
c++·io
罚酒饮得4 小时前
C++的QT实现接入DeepSeek,实现与DeepSeek对话功能
开发语言·c++·qt·ai·ai编程