参数化虚拟化会发生什么?

时间:2019-04-02 10:49:58

标签: c++ templates inheritance parameterized-virtuality

C ++模板-完整指南中的<16.4章<参数化虚拟化,由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的派生类。

问题:

  1. 参数化虚拟化期间在后台会发生什么?
  2. 生成的v_table会发生什么变化吗?
  3. 如何将模板参数中的virtual转移过来?

1 个答案:

答案 0 :(得分:3)

扩展@Quentin的评论

  

一旦Base模板专用于特定的T,一切就照常通过继承和虚拟覆盖进行。

让我们写出等效的非模板类

struct BaseNV : NotVirtual
{
    void func() // first definition of func
    { std::cout<< "Base::func()" <<std::endl; }
};

struct DerivedNV : BaseNV 
{
    void func() // hides BaseNV::func
    { std::cout<< "Derived::func()" <<std::endl; }
};

struct BaseIV : IsVirtual
{
    void func() // implicitly virtual, overrides IsVirtual::func
    { std::cout<< "Base::func()" <<std::endl; }
};

struct DerivedIV : BaseIV
{
    void func() // implicitly virtual, overrides BaseIV::func (and IsVirtual::func)
    { std::cout<< "Derived::func()" <<std::endl; }
};

int main()
{
    BaseNV *p1 = new DerivedNV();
    p1->func();
    delete p1;

    BaseIV *p2 = new DerivedIV();
    p2->func();
    delete p2;
}

See it live

  

参数化虚拟化期间在后台会发生什么?

Base<T>继承自T,并遵循继承规则

  

生成的v_table会发生什么变化吗?

只有普通的virtual机制。具体来说,在NotVirtual情况下,没有任何虚拟函数,因此可能不会有任何vtable。

  

模板参数中的虚拟如何转移?

按照正常的继承规则