我有以下代码:
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;
}
这不起作用,因为在基类的构造函数中不可能B::Compute
(它会调用不存在的A::Compute
)。
如何确保从派生类中的inited_val
函数填充Compute
?我可以从B
构造一个对象并在之后填充它或使用在构造函数之后直接调用的init函数,但这似乎容易出错(我可能会忘记这样做)。
(想象一下Compute
函数成本很高,并且只使用派生类中可用的数据。)
我找到了如何在http://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom上解决此问题的建议,并尝试使用create
函数实现该方法,但我不清楚如何在没有显式依赖的情况下编写A::create
在B
?
A* A::Create() {
A* p = ???;
inited_val = p->Compute();
return p;
}
答案 0 :(得分:0)
考虑使用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;
}
答案 1 :(得分:0)
您可以像这样实施Create
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>();