我有一个Base类,它包含一个成员变量std :: unique_ptr<基数>下一个。我有几个派生类Base。
我有一个非虚函数Base :: grow(),它接下来初始化。接下来总是指向调用grow的对象类型的对象。
通过Base :: grow()中的虚函数调用保证了下一个正确类型。
为每个派生类创建一个虚函数很麻烦且容易出错,因此我的问题是:我可以更加简洁地做到这一点吗?
我目前的最小工作示例如下:
#include <iostream>
#include <memory>
class Base{
public:
static const unsigned SIZE = 3;
std::unique_ptr<Base> next;
void grow(unsigned index){
if (index < SIZE){
print();
next = get_new();
next.get()->grow(index + 1);
}
}
virtual std::unique_ptr<Base> get_new(){
return std::unique_ptr<Base>(new Base());
//return std::move(std::unique_ptr<Base>(new Base())); (move not nec. see comments)
}
virtual void print (){
std::cout << "a Base ";
}
};
class Derived: public Base{
public:
virtual void print (){
std::cout << "a Derived ";
}
virtual std::unique_ptr<Base> get_new(){
return std::unique_ptr<Base>(new Derived());
}
};
int main(){
std::unique_ptr<Base> b;
b = std::unique_ptr<Base> (new Base());
b->grow(0);
std::unique_ptr<Base> c;
c = std::unique_ptr<Base> (new Derived());
c->grow(0);
}
输出是正确的:a base a Base a Base a Derived a Derived
总结:我想要一个消除繁琐get_new的解决方案,我希望Base :: grow根据调用对象的类型确定要创建的类型。我考虑过使用decltype,但没有成功。
与尝试在运行时确定类型相关的代码段:
typedef std::remove_reference<decltype(*this)>::type DynamicBase;
next = std::unique_ptr<DynamicBase>(new DynamicBase());
上面的DynamicBase总是被确定为Base,即使this
是指向Derived的指针
答案 0 :(得分:2)
你想要的是不可能的:你需要至少一个虚函数调用,即在每个派生中重写的虚方法。例如,考虑在另一个编译单元中定义派生类的情况。如果不使用多态,基类的代码如何获得未知类型的新派生对象?
答案 1 :(得分:0)
昨天我第一次遇到了奇怪的重复模板模式(crtp),我很确定它可以用来get_new
只定义一次。
crtp的想法在这里得到了很好的解释:https://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/