【问题标题】:Conditionally inherit from pure base class有条件地从纯基类继承
【发布时间】:2017-01-14 00:29:04
【问题描述】:

假设我有以下类定义

struct base {
  virtual int f() = 0;
};

struct A: public base {
  int f() final { return 1; }
};

struct B: public base {
  int f() final { return 2; }
};

是否可以将AB 转换为带有bool 参数的模板,该参数指定是否从base 继承?我有一些用例需要或不需要提供通用接口的基类。

假设AB 有很多成员函数,那么重复实现会很乏味。但是sizeof(A)sizeof(B) 很小。

【问题讨论】:

  • 您需要两个版本吗?假设base 仅包含抽象函数,则不应该有任何运行时成本。在您的示例中,您的优化器应该看到任何A 都将从那里使用f(),因为它是final
  • @Guvante :它使类型具有多态性,从而为它提供了一个 vtable。不是运行时成本,但仍然是成本。
  • @Guvante 继承类型的大小大了一个指针的大小,指针指向vtable。

标签: c++ templates inheritance c++14


【解决方案1】:

当然:

template <bool> struct A
{
    // ...
};

template <> struct A<true> : base
{
    // ...
};

(请注意,如果避免冗余,您可以使 A&lt;true&gt; 派生自 A&lt;false&gt;。)

例如:

template <bool> struct A
{
    void f() { std::cout << "A::f called\n"; }
};

template <> struct A<true> : A<false>, base
{
    void f() override { A<false>::f(); }
};

int main()
{
    A<false> a1;
    A<true> a2;
    a1.f();
    a2.f();
    static_cast<base&>(a2).f();
}

【讨论】:

  • 我认为这不允许A&lt;true&gt; a; base* p = &amp;a; p-&gt;f(); 正常工作。我猜这只有在base::f() 不是抽象的(钻石问题)时才会发生。您的实现是否使p-&gt;f() 调用比我原来的实现慢?
  • 有没有办法让A&lt;true&gt;::f()final?
  • 您需要复制声明(并通过A&lt;false&gt;::f() 调用另一个声明)。此外,如果您将 f() 放在 A&lt;false&gt; 中,它不会满足 base::f() 是抽象的要求。
  • @SU3:不,覆盖器必须在覆盖类中声明。让我编辑代码。
  • 谢谢,@KerrekSB。但我的问题之一是我想要一种方法来做到这一点,而不需要复制所有的函数定义。
【解决方案2】:

我想出了我正在寻找的更直接的方法,没有代码重复。

struct base {
  virtual int f() = 0;
};

struct empty_base { };

template <bool Inherit>
struct A final: public std::conditional_t<Inherit,base,empty_base> {
  int f() { return 1; }
};

【讨论】:

    【解决方案3】:

    由于您使用的是纯基类,因此区别不应该很重要,因为当您调用 A::f() 时,优化器将避免虚函数调用,因为永远不会有派生类实现不同版本的 f() .

    如果您不打算从A 继承,您也可以改为使用class A final : base,以避免必须将final 添加到每个函数。

    【讨论】:

    • 谢谢。我忘了你可以在类而不是函数上贴final
    • 你也可以class A sealed : public base { ... };
    • 什么是sealed?这是微软的扩展吗?
    • @SU3 :是的,这是 MS 对 final pre-C++11 的实现。 (在 C++/CLI 中它仍然是必需的,而不是 final,但这与这里无关。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多