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

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

 非抽象类继承和虚函数

#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(); // 动态多态:虽然是强转,但对象真实类型仍是 Derivedreturn 0;
}

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

#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()

返回类型 

#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()。

 多接口继承抽象类

#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

#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 + 多态)

#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()。

相关文章:

  • C++之虚函数 Virtual Function
  • Matlab画海洋与大气变量的时间序列并带标记面的三维折线图--来源粉丝
  • 如何对docker镜像存在的gosu安全漏洞进行修复——筑梦之路
  • Macvlan 网络类型详解:特点、优势与局限性
  • C++入门七式——模板初阶
  • Nacos启动报错
  • 软件测试行业核心知识点的系统化梳理
  • 使用 TensorFlow 和 Keras 构建 U-Net
  • Python语法系列博客 · 第9期[特殊字符] 函数参数进阶:*args、**kwargs 与参数解包技巧
  • 混合精度训练中的算力浪费分析:FP16/FP8/BF16的隐藏成本
  • 深度学习--mnist数据集实现卷积神经网络的手写数字识别
  • 探索大语言模型(LLM):Transformer 与 BERT从原理到实践
  • 【OpenGL】OpenGL学习笔记-1:VS2019配置OpenGL开发环境
  • PR第一课
  • Arduino项目中硬件包括哪些部分
  • 【MATLAB海洋专题】历史汇总
  • 链表面试题
  • 用思维导图解锁计算机科学导论的知识宝库
  • 取值运算符*和地址运算符
  • MYSQL初阶(暂为自用草稿)
  • 解除近70家煤电厂有毒物质排放限制,特朗普能重振煤炭吗?
  • 巡视杭州市工作动员会召开,市长姚高员表态
  • 美国佛罗里达州立大学枪击事件已致2人死亡
  • 中国足协、中足联:对浙江队外援阿隆·布彭扎不幸离世表示深切哀悼
  • G20召开发展工作组第二次会议,中方就美“对等关税”阐明立场
  • 最高检:一些不法分子以婚介之名实施诈骗,亟待治理和规范