【问题标题】:Possible to eliminate this base-class constructor?可以消除这个基类构造函数吗?
【发布时间】:2011-10-12 16:18:42
【问题描述】:

有没有办法消除 Foo 中的显式构造函数调用,并以某种方式将 Bar::len 分配给 Bar 的任何子类的大小?

class Bar
{
    size_t len_;

    Bar(size_t len) : len_(len) { }
};

class Foo : public Bar
{    
    Foo() : Bar(sizeof(Foo)) { }
};

【问题讨论】:

  • 哦,我明白了。由于 explicit Bar(size_t len) 之类的东西,显式构造函数可能是一个误导性术语。
  • 我不知道。 Bar 子类无法知道其最派生类型的大小。
  • 虚拟成员 len() 返回 sizeof(*this),在每个派生类中被覆盖怎么样?
  • @KerrekSB:难道虚函数不能在构造函数/析构函数中工作吗?
  • @MooingDuck:好吧,在那个版本中根本没有理由使用构造函数......

标签: c++ class templates subclass


【解决方案1】:

您可以使用“奇怪的递归模板”来通知基类派生类的类型:

template <typename Derived>
class Bar
{
    size_t len_;
protected:
    Bar() : len_(sizeof(Derived)) {}
};

class Foo : public Bar<Foo>
{
};

【讨论】:

  • 这有点违背继承的目的,因为你不能在不知道派生类型的情况下向下转换。
  • +1 用于 CRTP。 @Dani:该方法可以完美应用:class base { int len; base(int l) : len(l) {} }; template &lt;typename T&gt; class base_t : base { base_t() : base( sizeof(T) ) {} };,然后从base_t 模板而不是base 派生所有类。没有什么是无法通过额外的间接级别实现的:)
  • @Dani:你能详细说明一下吗?我真的不明白向下转换与我的答案或“继承的目的”有什么关系。
  • 从技术上讲,这个问题并没有说“直接子类”,所以我认为这不适用于孙辈。不过,它适用于一级继承。
  • 实际上@MikeSeymour 的回答完全符合要求——至少满足我的特定需求!
【解决方案2】:

虚拟继承可以做你想做的事:

#include <iostream>

class Bar
{
    size_t len_;
public:
    Bar(size_t len) : len_(len) {std::cout << len << '\n';}
};

class Foo : virtual public Bar //virtual inheritance
{    
    size_t foo_bigger_than_bar;
public:
    Foo() : Bar(sizeof(Foo)) { } //Bar only called if Foo is most derived
};

class Derived2: public Foo
{    
    size_t derived2_bigger_than_foo;
public:
    Derived2() : Bar(sizeof(Derived2)), Foo() { }
    // since Foo virtually derives from Bar, we have (get) to 
    // initialize Bar ourselves.
};

int main() {
    Foo f;
    std::cout << '\n';
    Derived2 d;
}

虚拟基类仅由派生最多的类初始化。例如,在创建Derived2 时,Foo 的构造函数将构造 Bar 对象,因为 Derived2 已经构造了它。这是钻石继承的关键,例如std::fstream
在这里演示:http://codepad.org/HUlLB4Uq

【讨论】:

  • 哦,我认为问题在于调整大小,但没有意识到它完全消除了初始化程序。哎呀。
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 2016-04-29
  • 2019-01-14
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 2016-05-05
  • 2015-06-21
相关资源
最近更新 更多