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.