Aqu*_*irl 16 c++ templates virtual-functions
来自Addison Wesley:C++模板
成员函数模板不能声明为虚拟.强加此约束是因为虚函数调用机制的通常实现使用固定大小的表,每个虚函数有一个条目.但是,在翻译整个程序之前,成员函数模板的实例化数量不固定.
以上引用是否意味着模板具有静态绑定,虚拟功能具有动态绑定,这就是不能有虚拟功能模板的原因?请查看是否可以用外行的语言进行解释.
Bo *_*son 24
是的,不.
解决虚函数调用的最常用方法是使用表("vtable"),其中每个虚函数映射到表中的索引.这或多或少要求您知道表的大小.
使用模板,将根据需要在不同模块中创建新功能.然后,您必须说服链接器在确定最终的函数数量后构建表,或者使用某种运行时结构在运行时搜索可用的函数.
在许多系统上,链接器是操作系统的一部分,对C++一无所知,因此选项有限.运行时搜索当然会对性能产生负面影响,可能对所有虚函数都有影响.
因此,最终决定将虚拟模板引入语言并不值得.
考虑:
struct X
{
template <typename T>
T incr(const T& t)
{
return t + 1;
}
};
Run Code Online (Sandbox Code Playgroud)
如incr()应用于不同的T类型,生成新函数.在里面说app.c++你有:
X x;
x.incr(7); // incr<int>()
x.incr(7.0); // incr<double>()
x.incr("hello"); // incr<const char*>()
Run Code Online (Sandbox Code Playgroud)
然后在编译时app.c++,它会看到3个函数 - 如果incr允许的话virtual- 它可以在X的虚拟调度表中为上面的三个实例创建空间.然后说它在运行时加载一个共享库,并且代码为那个图书馆有两个瞬间的X::incrfor uint32_t和std::string::const_iterator. dlopen()需要为已创建的对象增加现有的虚拟调度表,以便为两个新函数腾出空间.听起来不太可怕,但请考虑:
调用虚函数的每一段代码都必须知道这些函数的地址是否在运行时被一些偏移(由于动态加载额外的实例化),因此在每个虚拟调度中都会有额外的内存和性能成本
如果存在多重继承,或者派生类本身派生自,则编译器可能希望为整个虚拟函数集创建单个虚拟调度表(一个选项,有许多用于实现虚拟调度):在这种情况下,新的虚函数要么取代其他类的虚函数,要么与现有的虚函数脱节.同样,在任何方案中都有更多的运行时开销来管理它.
因此,非常罕见的情况下这可能是有用的,不值得妥协,并使非模板化虚拟的更常见情况复杂化.