Since once cannot call a overwritten function of a derived class in base class constructor, I would like to emulate this behavior (similar to what C#, Java, … are doing under the hood).
The most elegant I could come up with (from a signature side of view) is the following:
class Base {
protected:
virtual void init() {
}
template <typename T, typename ...U>
T internal_create(U&& u) {
T instance(std::forward<U>(u)...);
instance.init();
return instance;
}
};
class Derived : public Base {
protected:
Derived() = default;
virtual void init() override {
}
public:
static Derived create() {
return internal_create<Derived>();
}
};
Where create works as a substitute for the constructor (from public point of view) and the only way to instantiate an Object.
Question is whether this could be achieved simpler, since now every derived class has to implement create.
I can’t see that your code would compile. And I can’t see the point of the virtual
initmethod there, although it does suggest two phase construction. Which is just evil, which you can find out more about by reading Bjarne Stroustrup’s appendix E to “The C++ Programming Language”, especially section E3.5.The usual methods for doing derived class initialization in a base class constructor are outlined in the FAQ. Since I once convinced Marshall to add that FAQ item, I feel free to also direct you to my own blog.
In the future, remember that it is often a good idea to check out the FAQ first.
Oh, I forgot. The point about the C++ rules for dynamic type during construction, is to provide type safe construction. In Java and C# you can easily introduce a bug where you’re accessing some uninitialized members of a derived class, but not in C++.
Two phase construction ditches that type safety, and makes it difficult to write exception safe usage code, in return for the ability to code it up cleanly for an early 1990’s compiler (but really, who needs that ability).
The other usual solutions are designed to keep the type safety.