在c++中基类销毁期间是否有可能知道派生实例类型?
Is it possible to know the derived instance type during base class destruction in C++?
假设我有纯类A
和从A
派生的类B
、C
、D
等。是否有可能从A
的析构函数中知道哪个派生类正在被销毁?
那要看你需要什么了。当然有人会问为什么,这是一个值得怀疑的愿望。
不可能在编译时随时从基类中自动知道对象的动态类型。如果您想知道编译时的类型,唯一的解决方案是在基类类型本身中包含该信息,这基本上是CRTP模式。例如:
class BaseBase {
// body
};
template <typename D>
class Base : BaseBase {
//body
};
class Derived1 : public Base<Derived1> {
// body
};
class Derived2 : public Base<Derived2> {
// body
};
这样,Base
的析构函数将在编译时"知道"派生类的类型。然而,这有一个缺点,Derived1
和Derived2
的共同超类型是而不是 Base
,但是BaseBase
和BaseBase
的析构函数无法知道(并且您可能会回到原点)。
如果你只想在运行时知道(这意味着你不能直接做像DerivedClass::something
这样的事情),例如出于调试原因,你可以在基类中添加一个包含info类型的成员:
class Base {
protected:
type_info const* type;
public:
Base() {
type = &typeid(this);
}
};
class Derived : public Base {
public:
Derived() {
type = &typeid(this);
}
};
请注意,这依赖于Base
构造函数将在Derived
构造函数之前运行的事实,因此type
指针将指向当前已构造的最派生类。
可以在使用CRTP时完成,如下所示:
template <typename TDerived>
class Base {};
class Derived : public Base<Derived> {};
那么Base
在任何时候都知道派生类型
CRTP的问题是您有不同的基类型,您不能将其用于动态多态性。
如果您不需要派生对象的实际类型,但希望根据它执行代码,则有不同的可能性。注意,不能在析构函数中调用任何虚函数。但是,您可以:
1。添加一个类型成员变量(可以是std::type_info
,枚举或其他)并在其上手动调度。
2。使用一种技术作为虚拟构造函数习惯用法的对应,在显式销毁之前调用函数(通过delete
或类似的方法)。然而,这要么可以被遗忘,要么(如果强制执行)严重限制了销毁对象的方式。
3。您可以使用策略模式:
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>())
{
}
};
注意,对于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([] () { ... })
{
}
};
重要:您必须确保策略对象或函数对象不引用派生类的任何成员,因为派生对象在调用时已被销毁。如果需要访问成员属性,最好直接重新定义析构函数。
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 有可能使shared_ptr协变吗
- 有可能在信号处理程序中设置promise吗
- 是否有可能实现O(N)时间和O(1)空间解决方案,以实现C++中的字符串循环移位
- 是否有可能构建面向Linux和Windows的.Net Core C++ / CLI应用程序?
- 是否有可能使用debug_info获取ELF文件的源代码?
- C++,是否有可能/如何定义在.h和.cpp源文件中调用函数的类构造函数
- 有可能在C++中有类的查找表吗
- 是否有可能让 c++ dll 在后台运行 python 程序并让它填充向量图?如果是这样,如何?
- 向量的大小是否有可能为 1 但其中的元素数量为零?
- 是否有可能编写新的叮当声现代化规则?
- 是否有可能通过指向另一个未关联的子对象的指针来获取指向一个子对象的指针?
- 是否有可能通过演绎指南实现整个 std::make_tuple 功能?
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 是否有可能有一个派生类继承最终函数但创建相同的函数(而不是重写)
- C++ 基类是否有可能具有派生类参数的函数
- 是否有可能有一个基类方法来调用它的所有派生类的相同(但被重写的方法)?
- 在c++中基类销毁期间是否有可能知道派生实例类型?
- 基类是否有可能具有不在派生类中的函数?