简体   繁体   English

使用派生类成员进行父类的初始化

[英]Using derived class members for the initialization of the parent class

I would like to initialize a class B that's derived from class A , and where in B I construct a cache first that is used with the construction of A , eg, 我想初始化类B这是一个从类派生A ,并且其中在B我构造的高速缓存首先进行使用的建设A ,例如

class B: public A {

public:
  B(): A(cache_), cache_(this->buildCache_())

protected:
  const SomeDataType cache_;

private:
  SomeDataType
  buildCache_() const
  {
    // expensive cache construction
  }

}

This is not going to work though because the parent object A is always initialized first (before cache_ is filled). 不会工作,虽然因父对象A总是先初始化(前cache_充满)。

(For the sake of completeness: The cache_ is used many more times in classes derived from B .) (出于完整性考虑: cache_在从B派生的类中被多次使用。)

As an alternative, I could do 作为替代,我可以做

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_;
  }

}

This has the disadvantage that buildCache_() can't be const . 这样做的缺点是buildCache_()不能为const Also, GCC complains that 另外,海湾合作委员会抱怨说

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

Is there a more appropriate solution to this? 有没有更合适的解决方案?

What you are doing as-is is undefined behavior, from [class.base.init]/14, emphasis mine: 您所做的是[class.base.init] / 14中未定义的行为,重点是我的:

Member functions (including virtual member functions, 10.3) can be called for an object under construction. 可以为正在构造的对象调用成员函数(包括虚拟成员函数10.3)。 Similarly, an object under construction can be the operand of the typeid operator (5.2.8) or of a dynamic_cast (5.2.7). 同样,正在构造的对象可以是typeid运算符(5.2.8)或dynamic_cast (5.2.7)的操作数。 However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer ) before all the mem-initializer s for base classes have completed, the result of the operation is undefined . 但是,如果在所有基类的mem-initializer完成之前,在ctor初始化程序 (或直接或间接从ctor初始化程序调用的函数)中执行了这些操作,则操作的结果是不确定的

What you want to do instead is use the Base-from-Member idiom : 您想要做的是使用“ 从成员开始”成语

class Cache {
protected:
    const SomeDataType cache_;
};

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

From C++11, you may use forward constructor: 从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_;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM