【问题标题】:Optional variable in a class类中的可选变量
【发布时间】:2021-04-30 21:22:00
【问题描述】:

我有一个类 A 和类 B,它们都有相同的方法和变量,但 B 有一个额外的变量(它完全独立于其他类成员)。 所以它会是这样的:

class A
{
    void Foo();
    bool m_var;
}

template< class T >
class B< T >
{
    // Same stuff
    void Foo();
    bool m_var;

    // Unique stuff
    T m_data;
}

通常,我会使用继承B : public A,但我想让这些类保持超级紧凑,并且我不想在其中包含 vtable ptr(因为无论如何我都不会使用多态性)。实现这一目标的最佳方法是什么?我在考虑模板及其专业化 - 有 A&lt;T&gt;A&lt;void&gt; 类,但我需要删除一些东西,而不是添加。我可以使用任何智能模板技巧吗? 我还在考虑创建具有所有常见功能的基类(没有虚拟 dtor)作为私有嵌套类和继承类 A&lt; T &gt; : public Base 和空 B : public Base 作为公共嵌套类。它不允许外部的任何人使用基类 ptr,但这听起来不像是最纯粹的解决方案......我的问题有什么“有效”的解决方案吗?

【问题讨论】:

  • 继承 != 多态性。
  • Static Polymorphism 可能是?
  • B : public A 本身并没有引入 vtable 指针。直到你真正添加了一个虚拟成员函数。
  • 一个“vtable”是用于虚拟的。简单的继承并不意味着虚拟性。
  • 只有当您计划通过指向父类的指针引用子类时才需要虚拟析构函数(即使用您试图避免的虚拟多态性)。如果您不打算这样做,那么非虚拟(或默认)析构函数是无害的。

标签: c++ templates inheritance


【解决方案1】:

只要你不使用virtual这个词,你就不会得到vtable。但是你认为继承是这个问题的尴尬解决方案是正确的。 Rust、Scala 和 Haskell 等语言有一个单元类型 () 用于我们不关心的数据。 C++ 用void 来近似(虽然效果很差),但它实际上只用作函数返回类型。我的建议是创建自己的行为良好的单元类型。

struct Unit {};

很好,空的类型。 Unit 只有一个有意义的不同实例,即Unit()。那么A 就是B&lt;Unit&gt;B&lt;Unit&gt; 中的 Unit m_data 不包含实际信息,可能会被编译器优化掉。

【讨论】:

【解决方案2】:

正如已经回答的那样,vtable 指针仅在需要时才添加到类中。只要在您的基类或派生类中没有任何标记为 virtual 的内容,编译器就不会为您的类型生成 vtable。

如果你想在写 B 的时候重用 A,你为什么不能用普通的旧作文?

class A {
    bool _var;

public:
    explicit A(bool v);

    void foo();

    // accessors, which could be constexpr
    bool var() const;   // get
    void var(bool n_v); // set

};

template<class T>
class B {
    T _data;
    A _a;    

public:
    B( /* params */);

    void foo() { this->_a.foo(); }
    
    // forward to A
    bool var() const { return this->_a.var(); }     // get
    void var(const bool n_v) { this->_a.var(n_v); } // set

    // add more stuff here
};

如果你真的很讨厌恶作剧,你可以考虑采用私有继承路线,这在功能上是相同的(但不太干净,恕我直言):

template<class T>
class B : private A {
    T _data;

public:
    B( /* params */);

    using A::foo; // reexports A::foo() as B::foo()
    
    // generates
    // - bool B::var()
    // - void B::var(bool)
    using A::var; 

    // add more stuff here
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 2012-06-30
    • 2021-07-22
    • 1970-01-01
    • 2016-11-01
    • 2016-02-03
    相关资源
    最近更新 更多