【发布时间】:2019-04-02 10:49:58
【问题描述】:
C++ 模板 - 完整指南 中的第 16.4 章 Parameterized Virtuality,作者 David Vandevoorde 和 Nicolai M. Josuttis,说:
C++ 允许我们通过以下方式直接参数化三种实体 模板:类型、常量(“非类型”)和模板。然而, 间接地,它还允许我们参数化其他属性,例如 成员函数的虚拟性。
该章说明了以下代码:
#include <iostream>
struct NotVirtual
{};
struct IsVirtual
{
virtual void func() {;}
};
//---------------------//
template<typename T>
struct Base : T
{
void func()
{ std::cout<< "Base::func()" <<std::endl; }
};
template<typename T>
struct Derived : Base<T>
{
void func()
{ std::cout<< "Derived::func()" <<std::endl; }
};
//---------------------//
int main()
{
Base<NotVirtual> *p1 = new Derived<NotVirtual>();
p1->func();
delete p1;
Base<IsVirtual> *p2 = new Derived<IsVirtual>();
p2->func();
delete p2;
}
在线示例:https://rextester.com/OAGC66937
我了解这种技术的用法,但不幸的是,这本书没有提供关于这种情况如何发生的任何进一步细节。可以看到Base其实是继承自模板参数T的派生类。
问题:
- 在参数化虚拟过程中,后台会发生什么?
- 生成的 v_table 中是否发生了什么?
- 模板参数中的
virtual是如何传递过来的?
【问题讨论】:
-
一旦
Base模板专门用于特定的T,一切都会通过继承和虚拟覆盖照常进行。虚函数或任何东西没有特殊情况。你到底在哪里迷路了? -
@Quentin:如果
Base::func是Derived的基类,它不应该是虚拟的吗? -
不,您可以很好地从父类继承和隐藏函数,而不需要它们是
virtual,当然它们不会被动态调度。请注意Base和Derived是模板,而不是类,这对于理解它们如何在实例化时生成两个完全独立的类链至关重要。这里演示的技巧是在继承链的顶部注入IsVirtual,以便它实际上声明一个virtualfunc,然后在整个派生类中保持virtual。这使它看起来像Base的func已经“变成”virtual。 -
不是本身。取决于程序员的实现和目标。不在派生类中声明虚函数并重新声明它是完全有效的。
-
@Quentin:这部分是我不清楚的:“......在整个派生类中仍然是虚拟的”。我认为通过将
Base::func()设置为non-virtual,Derived也将是non-virtual。我不知道通过在继承链中向上两级声明函数virtual,它仍然会保留virtual。
标签: c++ templates inheritance