将多态成员变量实例化为适当的类型
Instantiate polymorphic member variable to be of appropriate type
我有一个Baseclass,里面有一个成员变量std::unique_ptr next。我有几个派生的 classes of Base.
我有一个非虚拟函数 Base::grow() ,它接下来会初始化。 next 将总是 指向调用grow 的对象类型的对象。
通过 Base::grow() 中的虚函数调用可以保证 next 是正确的类型。
为每个派生的 class 创建一个虚函数既麻烦又容易出错,因此我的问题是:我可以更简洁地做到这一点吗?
我当前的最小工作示例如下所示:
#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 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
的指针也是如此
你想要的是不可能的:你需要至少一个虚函数调用,即在每个派生中重写的虚方法。例如,考虑在另一个编译单元中定义派生的 class 的情况。如果不使用多态性,基class的代码将如何获得一个新的未知类型的派生对象?
昨天我第一次遇到奇怪的重复模板模式 (crtp),我相当确定它可以用于 get_new
只定义一次。
这里很好地解释了crtp的思想:https://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/
我有一个Baseclass,里面有一个成员变量std::unique_ptr
我有一个非虚拟函数 Base::grow() ,它接下来会初始化。 next 将总是 指向调用grow 的对象类型的对象。
通过 Base::grow() 中的虚函数调用可以保证 next 是正确的类型。
为每个派生的 class 创建一个虚函数既麻烦又容易出错,因此我的问题是:我可以更简洁地做到这一点吗?
我当前的最小工作示例如下所示:
#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 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
你想要的是不可能的:你需要至少一个虚函数调用,即在每个派生中重写的虚方法。例如,考虑在另一个编译单元中定义派生的 class 的情况。如果不使用多态性,基class的代码将如何获得一个新的未知类型的派生对象?
昨天我第一次遇到奇怪的重复模板模式 (crtp),我相当确定它可以用于 get_new
只定义一次。
这里很好地解释了crtp的思想:https://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/