使用派生类成员初始化父类

Using derived class members for the initialization of the parent class

本文关键字:初始化 父类 成员 派生      更新时间:2023-10-16

我想初始化一个从类A派生的类B,并且在B中我首先构建一个与A结构一起使用的缓存,例如,

class B: public A {
public:
  B(): A(cache_), cache_(this->buildCache_())
protected:
  const SomeDataType cache_;
private:
  SomeDataType
  buildCache_() const
  {
    // expensive cache construction
  }
}

这是不能工作,因为父对象A总是首先初始化(在cache_被填充之前)。

(为了完整起见:cache_B派生的类中使用的次数更多)

作为替代,我可以做

class B: public A {
public:
  B(): A(this->buildCache_())
protected:
  const SomeDataType cache_;
private:
  SomeDataType
  buildCache_()
  {
    // expensive cache construction
    // fill this->cache_ explicitly
    return cache_;
  }
}

这样做的缺点是buildCache_()不能是const。另外,GCC抱怨

warning: ‘B::cache_’ should be initialized in the member initialization list [-Weffc++]

是否有更合适的解决方案?

你所做的是未定义的行为,从[class.base]。/14,强调mine:

可以为正在构造的对象调用成员函数(包括虚成员函数,10.3)。类似地,正在构造的对象可以是typeid操作符(5.2.8)或dynamic_cast操作符(5.2.7)的操作数。但是,如果在变量初始化器中执行这些操作(或在直接调用的函数中),则在基类的所有mem-初始化器s完成之前,或间接地从元素初始化器)中获取结果.

你要做的是使用Base-from-Member的习惯用法:

class Cache {
protected:
    const SomeDataType cache_;
};
class B : private Cache, public A {
public:
    B() : Cache(), A(cache_)
    { }
};

从c++ 11开始,你可以使用前向构造函数:

class B: public A
{
public:
  B(): B(B::buildCache_()) {}
private:
  B(SomeDataType&& cache) : A(cache), cache_(std::move(cache)) {}
private:
  static SomeDataType buildCache_()
  {
    // expensive cache construction
  }
protected:
    const SomeDataType cache_;
};