我有一个类似于此的基类(但以下内容不能编译):
struct Base {
virtual void foo()=0;
virtual void init()
{
using Derived = typename std::remove_reference<decltype(*this)>::type;
*this = Derived(); // does not compile as Base is an abstract class
}
};
Base
有很多派生类,我想要做的是让它的所有派生类都有init()
函数继承自Base
并初始化自己(通过调用它们构造函数)。如果他们愿意,也允许他们覆盖init()
。
问题:
我知道它没有编译。如果我的Base不是抽象类,它会起作用吗?我想知道this
指针是否会被解释为派生对象指针?
如何实现我的目标?
------------------------------- EDIT ------------ --------------------------
澄清一下,
init()
函数实际上正在重置。它将每个派生对象重置为其默认状态。我希望它在具有这种默认行为的Base类中,并且如果派生类想要一些不同的reset(),它们可以自由地覆盖它。
答案 0 :(得分:1)
一些用户在评论中提到了CRTP(奇怪的重复模板模式),没有显示具体的解决方案,所以这里有一个:
template <typename CRTP>
struct Base {
virtual void foo()=0;
virtual void init()
{
static_cast<CRTP&>(*this) = CRTP{};
}
};
struct Derived : public Base<Derived> {
void foo() override {}
};
答案 1 :(得分:0)
您希望根据派生类的类型调用不同的函数。这是C ++中的多态。你可以随意使用嫌疑人:
CRTP是完成第二种方法的一种方法,让派生在继承点说出它的真实类型。
一种非常 hacky 方式来完成第二种方式,很明显我不推荐,但可能需要在一个功能失调的组织中,你没有其他的options:尝试dynamic_cast到派生类的各种选项。这可能很脆弱。但即使有一个重置功能,而不是使用构造和破坏是脆弱的。
我建议重新评估您对重置成员功能的需求,询问您要尝试使用它完成的内容,并尽量不要降低工作产品的质量作为与您的组织交互的最终目的。 (我的意见。)
答案 2 :(得分:0)
选项1/2
也许你可以拥有一个执行你想要的行为的模板功能。然后可以从需要默认行为的每个派生类显式调用它。通过使函数为纯虚拟,您可以确保在每个派生类中实现它。创建一个智能指针类,它包含指向原始对象的指针,以及指向可以重新启动对象的函数的指针。
#define DEFAULTINIT \
virtual void init()\
{\
DefaultBehavior(this);\
}\
template <typename T> void DefaultBehavior(T *x)
{
*x = T();
}
struct Base {
virtual void init() = 0;
};
struct Derived : virtual public Base
{
DEFAULTINIT;
};
选项2/2
创建一个智能指针类,它包含指向原始对象的指针,以及指向可以重新启动对象的函数的指针。
struct Base {
virtual ~Base()=0;
};
struct Derived : virtual public Base {
int a = {};
};
template <typename T>
void default_initter(Base *b)
{
T *d = dynamic_cast<T *>(b);
*d = T();
}
typedef void (*initter)(Base *);
struct SmartPointer
{
template <typename T>
SmartPointer(T *d) : base(d), init(default_initter<T>) {};
Base * base;
initter init;
};
#include <iostream>
int main()
{
Derived *d = new Derived();
SmartPointer *sp = new SmartPointer(d);
d->a = 5;
std::cout << d->a << std::endl;
sp->init(sp->base);
std::cout << d->a << std::endl;
}