很多C++ 标准库 使用模板而不是继承来实现多态性。 这是一个众所周知的话题关于原因²。有数百个关于这个主题的视频和博客文章。
至于标准库中确实使用继承的部分,我只能想到
我的问题是:标准库的这两个部分必须满足哪些特殊要求/约束/目标/某些东西,要求(或要求!³)它们使用继承? ⁴
定义都可以在headers中使用。如果由于某种原因需要独立编译算法,然后“链接”到客户端程序,那么(我的理解是)算法将必须使用某种类型的类型擦除,因此需要某种类型的运行时多态性。 (²) 是的,问题涉及STL。但我想即使接受这种模糊性,我认为自由的模板化部分和虚拟部分之间的不平衡仍然适用。
(³) 我想知道这两个库是否会基于C++20 的模块
进行不同的设计。(⁴)澄清:我不是在寻找类似的答案(参考诊断库)“哦,这很简单!这是因为你想要
std::logic_error
,std::runtime_error
和其他例外来实现
what
,因此您可以在异常上调用
.what
,而无需实际知道其具体类型!”,因为单遍算法也“希望”其迭代器输入来实现
operator++
和 operator*
,但它们并不需要所有迭代器共享基类!
简单地阅读评论并尝试解决它们,促使我更深入地思考,我想我已经得到了一半的答案,一半是关于诊断库的。
给定如下所示的 TU,这可以
throw
// foo.hpp
void foo(bool b);
// foo.cpp
#include "foo.hpp"
void foo(bool b) {
if (b)
throw std::logic_error{"oops"};
else
throw std::runtime_error{"oops"};
};
它可以与另一个捕捉这样的异常的 TU 链接void bar(bool b) {
try {
foo(b);
} catch(std::exception const& e) {
// stuff I know
} catch(...) {
// stuff I don't know
}
}
在这样的场景中,一个 TU 中生成的异常要被另一个 TU 捕获的唯一方法是前一个 TU 生成的异常必须是后一个 TU 捕获的异常类的子类。
所以我猜想,就诊断库而言,它从根本上使用基于继承的异常层次结构,因为它希望允许异常处理跨越多个翻译单元,这可能就是人们希望拥有异常机制的全部意义所在完全没有。