网站首页 > 技术文章 正文
多态(Polymorphism),将不同的特定行为关联到单一的通用符号,这种能力是面向对象编程的基石,在语言层面是使用类型继承+虚拟函数+指针访问,编译器则负责把vptr、vtable、RTTI等塞进去,在程序运行时通过动态绑定机制实现正确调用,所以也称为动多态。
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() override {}
};
class Rectangle : public Shape {
public:
void draw() override {}
};
void draw_all(const std::vector<Shape *> &shapes) {
for (auto *shape : shapes) {
shape->draw();
}
}
模板也同样具备将不同的特定行为关联到单一符号的能力,不过这种多态处理发生在编译期,我们称它为静多态。
template <typename Drawable>
void draw_all(const std::vector<Drawable> &drawable_objs) {
for (auto obj : drawable_objs) {
obj.draw();
}
}
从上面的代码来看,两种多态的差别还是很大的。
动多态基于某个抽象接口,这个抽象类需要明确定义(上面的Shape类定义),语义上非常清晰,同时通过基类指针,不同子类对象可以放置到同一个容器里,处理方式也显得更为优雅。缺点是间接访问的开销,执行效率略有损失。
静多态的语义约束看起来没有那么明显,上面的例子是要求类型有void draw()成员函数。另外你无法直接把具备draw成员函数的不同类型对象放置在同一个容器里(除非你通过某种代理类)。优点是多态在编译期绑定,运行性能好。
C++20引入了概念(Concepts),可以理解为静多态的某种语义接口(通过concept的定义),这样代码的表达能力就大大增强了,同时也减少了类型误用导致巨大篇幅的编译错误信息的产生。
template <typename T>
concept Drawable = requires(T a) {
a.draw();
};
template <Drawable T>
void draw_all(const std::vector<T> &drawable_objs) {
for (auto obj : drawable_objs) {
obj.draw();
}
}
for循环正确的使用方式应该是auto&,这里使用传值语义只是想说明在静多态里不再需要通过指针或引用来使用通用接口了。
模板技术引入的静多态能力也给设计模式的带来了更多实现方式的选择,比如说桥接模式、策略模式等等,经典实现都是利用了动多态,通过基类指针屏蔽不同子类的类型差异。利用模板参数的静多态可以达到类似的实现效果,只是执行程序的尺寸比起动多态要大一些。
静多态的广泛应用形成了一种新的软件设计范式 - 范型编程。到底什么是范型程序设计,有很多不同的看法:使用模板参数将类型参数化可以看作是范型编程最直接的应用,但真正的范型设计应该涉及到多个模板参数在不同维度的组合,不同的类或函数依赖于其间的语义约束或概念,高效地实现各种功能。一个最直观的例子就是STL本身:各种底层不同数据结构的容器,针对容器数据的各种算法,连接其间的核心概念是它们的粘合剂 - 迭代器。容器提供自己的迭代器实现,算法利用各种迭代器的标准操作语义,最大效率地实现算法。
- 上一篇: C++之异常处理机制
- 下一篇: C++面向对象(5)
猜你喜欢
- 2025-01-20 C++|类型转换与运行时类型安全检查
- 2025-01-20 C++Qt开发——事件处理函数
- 2025-01-20 百度Linux C++后台开发面试题(个人整理)
- 2025-01-20 怎样才算学会了C++基础,一篇文章学习了解(包含Qt内容)
- 2025-01-20 C++通过aidl与Android系统服务通信(一)
- 2025-01-20 学习阅读C++编译器错误:函数声明中的荒谬错误
- 2025-01-20 朝文分享(54):深入C++(二十一)——多态
- 2025-01-20 c++多态
- 2025-01-20 深入探讨C++多线程性能优化
- 2025-01-20 【C++】C++ 11 新特性:使用示例
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)