C++ 在C+中销毁基类时,是否可能知道派生实例类型+;?
假设我有纯类C++ 在C+中销毁基类时,是否可能知道派生实例类型+;?,c++,inheritance,destructor,C++,Inheritance,Destructor,假设我有纯类A和类B,C,D,等等,都是从A派生出来的。可以从A的析构函数中知道正在销毁哪个派生类吗?可以在使用时执行,如下所示: template <typename TDerived> class Base {}; class Derived : public Base<Derived> {}; 模板 类基{}; 派生类:公共基{}; 然后Base随时知道派生类型。这取决于您需要什么。当然,这里有人会问为什么,这是一个值得怀疑的愿望 在编译时,不可能随时从基类自
A
和类B
,C
,D
,等等,都是从A
派生出来的。可以从A的析构函数中知道正在销毁哪个派生类吗?可以在使用时执行,如下所示:
template <typename TDerived>
class Base {};
class Derived : public Base<Derived> {};
模板
类基{};
派生类:公共基{};
然后Base
随时知道派生类型。这取决于您需要什么。当然,这里有人会问为什么,这是一个值得怀疑的愿望
在编译时,不可能随时从基类自动了解对象的动态类型。如果您想在编译时知道该类型,唯一的解决方案是将该信息包含在基类类型本身中,这基本上就是CRTP模式。例如:
class BaseBase {
// body
};
template <typename D>
class Base : BaseBase {
//body
};
class Derived1 : public Base<Derived1> {
// body
};
class Derived2 : public Base<Derived2> {
// body
};
请注意,这取决于Base
构造函数将在派生的
构造函数之前运行,因此类型
指针将引用当前已构造的最派生的类。CRTP的问题是,您有不同的基类型,不能用于动态多态性
如果您不需要派生对象的实际类型,但希望根据它执行代码,则有不同的可能性。请注意,您不能调用析构函数中的任何虚拟函数。但是,您可以:
一,。添加一个类型成员变量(可以是std::type_info
、一个枚举或其他任何变量)并对其手动分派
二,。使用技术作为的对应项,在显式销毁之前调用函数(通过delete
或类似方式)。但是,这可能会被遗忘,或者(如果强制)严重限制了销毁对象的方式
三,。您可以使用策略模式:
class Base
{
struct Strategy
{
virtual ~Strategy();
virtual void onDestroy() = 0;
}
std::unique_ptr<Strategy> strategy;
public:
explicit Base(std::unique_ptr<Strategy> strategy)
: strategy(std::move(strategy))
{
}
virtual ~Base()
{
strategy->onDestroy();
}
};
class Derived1 : public Base
{
struct Strategy1 : Strategy
{
virtual void onDestroy() { ... }
};
public:
Derived1()
: Base(std::make_unique<Strategy1>())
{
}
};
类基
{
结构策略
{
虚拟策略();
虚拟空onDestroy()=0;
}
std:独特的ptr策略;
公众:
显式基础(标准::唯一的ptr策略)
:策略(标准::移动(策略))
{
}
虚拟~Base()
{
策略->onDestroy();
}
};
类Derived1:公共基
{
结构策略1:策略
{
虚拟空onDestroy(){…}
};
公众:
Derived1()
:Base(std::make_unique())
{
}
};
请注意,对于C++11函数对象,这变得相当简单:
class Base
{
std::function<void()> strategy;
public:
explicit Base(std::function<void()> strategy)
: strategy(std::move(strategy))
{
}
virtual ~Base()
{
strategy();
}
};
class Derived1 : public Base
{
public:
Derived1()
: Base([] () { ... })
{
}
};
类基
{
功能策略;
公众:
显式基(std::函数策略)
:策略(标准::移动(策略))
{
}
虚拟~Base()
{
策略();
}
};
类Derived1:公共基
{
公众:
Derived1()
:Base([](){…})
{
}
};
重要提示:您必须确保策略对象或函数对象不引用派生类的任何成员,因为派生对象在调用时已被销毁。如果您需要访问成员属性,最好直接重新定义析构函数。我猜您的意思是自动,也就是说,编译器会告诉您?“手动”解决方案是添加一些存储最派生类型的数据成员,例如type\u info const&
.No。至此,所有衍生零件都消失了。为什么需要这个?我想知道,如果将基本析构函数标记为virtual并在每个派生函数中重写析构函数,是否可以达到相同的目的classes@Jimmy:析构函数在这方面很特别,因为重写B::~B仍将调用A::~A。回到A::~A中,您不知道自己来自何处。您忘记了在第二个示例中继承Base
)
class Base
{
std::function<void()> strategy;
public:
explicit Base(std::function<void()> strategy)
: strategy(std::move(strategy))
{
}
virtual ~Base()
{
strategy();
}
};
class Derived1 : public Base
{
public:
Derived1()
: Base([] () { ... })
{
}
};