简体   繁体   中英

Need help on the Dynamic Binding During Initialization idiom

I have the following code:

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

which will not work because it's not possible to B::Compute in the constructor of the base class (it would call A::Compute which does not exist).

How can I ensure that inited_val is filled from the Compute function in the derived class? I could construct an object from B and fill it afterwards or using an init function that is called directly after the constructor, but that seems error-prone (I might forget to do so). (Imagine the Compute function is costly and uses data only available in the derived class.)

I found proposals how to solve this problem on http://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom and tried to implement the approach with a create function, but it's not clear to me how to write A::create without an explicit dependency on B ?

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

Consider using 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;
}

You can implement Create like this

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

And you can use it like this

auto b = Create<B>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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