需要有关初始化期间动态绑定习惯用法的帮助

Need help on the Dynamic Binding During Initialization idiom

本文关键字:习惯 动态绑定 惯用法 帮助 初始化      更新时间:2023-10-16

我有以下代码:

class A {
  public:
    A();
    virtual int Compute() = 0;
    int inited_val;
};
class B: A {
  public:
    B(int data): mydata(data) {};
    int Compute();
    int mydata;
};
A::A() {
  inited_val = Compute();
};
int B::Compute() {
  return mydata; // long computation...
}
int main() {
  B b(42);
  return 0;
}

这将不起作用,因为在基类的构造函数中CCD_ 1是不可能的(它将调用不存在的CCD_。

如何确保从派生类中的Compute函数填充inited_val?我可以从B构造一个对象,然后填充它,或者使用在构造函数之后直接调用的init函数,但这似乎很容易出错(我可能会忘记这样做)。(假设Compute函数代价高昂,并且只使用派生类中可用的数据。)

我在上找到了解决这个问题的建议http://isocpp.org/wiki/faq/strange-inheritance#calling-来自ctor习语的virtuals,并试图用create函数实现该方法,但我不清楚如何在不显式依赖B的情况下编写A::create

A* A::Create() {
  A* p = ???;
  inited_val = p->Compute();
  return p;
}

考虑使用CRTP:

template<class T> class Wrapper : public T
{
public:
  template<class... Types>
  Wrapper(Types&&... Args)
    : T(std::forward<Types>(Args)...)
  {
    inited_val = Compute();
  }
};  

int main() 
{
  Wrapper<B> b(42);
  return 0;
}

您可以像这个一样实现B::Compute0

template <class T>
static std::unique_ptr<typename std::enable_if<std::is_base_of<A, T>::value, T>::type> Create()
{
    auto t = std::make_unique<T>();
    inited_val = t->Compute();
    return t;
}

你可以像这个一样使用它

auto b = Create<B>();