【问题标题】:What happens in parameterized virtuality?参数化虚拟会发生什么?
【发布时间】: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的派生类。

问题:

  1. 在参数化虚拟过程中,后台会发生什么?
  2. 生成的 v_table 中是否发生了什么?
  3. 模板参数中的virtual 是如何传递过来的?

【问题讨论】:

  • 一旦Base 模板专门用于特定的T,一切都会通过继承和虚拟覆盖照常进行。虚函数或任何东西没有特殊情况。你到底在哪里迷路了?
  • @Quentin:如果Base::funcDerived 的基类,它不应该是虚拟的吗?
  • 不,您可以很好地从父类继承和隐藏函数,而不需要它们是virtual,当然它们不会被动态调度。请注意BaseDerived 是模板,而不是类,这对于理解它们如何在实例化时生成两个完全独立的类链至关重要。这里演示的技巧是在继承链的顶部注入IsVirtual,以便它实际上声明一个virtualfunc,然后在整个派生类中保持virtual。这使它看起来像Basefunc 已经“变成”virtual
  • 不是本身。取决于程序员的实现和目标。不在派生类中声明虚函数并重新声明它是完全有效的。
  • @Quentin:这部分是我不清楚的:“......在整个派生类中仍然是虚拟的”。我认为通过将Base::func() 设置为non-virtualDerived 也将是non-virtual。我不知道通过在继承链中向上两级声明函数virtual,它仍然会保留virtual

标签: c++ templates inheritance


【解决方案1】:

扩展@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&lt;T&gt;继承自T,遵循继承规则

生成的 v_table 中是否发生了什么?

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

模板参数中的virtual是怎么传过来的?

按照正常的继承规则

【讨论】:

  • @Quentin 哎呀,确实
  • 谢谢。这里的评论非常有用:// implicitly virtual, overrides IsVirtual::func。我不知道在继承链中向上两级声明函数virtual,仍然是virtual
猜你喜欢
  • 1970-01-01
  • 2013-04-02
  • 2022-07-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
相关资源
最近更新 更多