确保dynamic_cast不会导致未定义的行为C ++
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了确保dynamic_cast不会导致未定义的行为C ++相关的知识,希望对你有一定的参考价值。
直到今天,我认为如果我有类A
和B
与任何方式无关,使用指针的dynamic_cast
将无法返回nullptr
。现在我已经读到这会导致未定义的行为......
当
dynamic_cast
用于构造函数或析构函数(直接或间接),而expression指的是当前正在构造/销毁的对象时,该对象被认为是派生最多的对象。如果new_type
不是构造函数/析构函数自己的类或其基础的指针或引用,则行为未定义。
我有这样的代码:
class ActorComponent
{
ActorComponent* m_parent;
public:
template <typename _type>
_type* getParent() const {
return dynamic_cast<_type*>(m_parent);
}
ActorComponent(ActorComponent* parent) {
// using `getParent` inside the constructor:
auto p = this->getParent<int>(); // `int` obviously isn't base of the ActorComponent
}
};
我需要将_type
限制为类型
- 等于
ActorComponent
- 源自
ActorComponent
......可能还有更多。
问题是:如何在编译时确保dynamic_cast
对这样的_type
不会导致不确定的行为?会很简单
template <typename _type,
typename = std::enable_if_t< std::is_base_of_v<ActorComponent, std::remove_cv_t<_type> > || std::is_same_v<ActorComponent, std::remove_cv_t<_type> > >
总能工作?
tl; dr没关系。出于某种原因,您选择的条件显然不适用于您的代码。
你的报价:
如果new_type不是指向构造函数/析构函数自己的类或其基础的指针或引用,则行为是未定义的。
显然是在构造函数或析构函数中使用dynamic_cast
,尽管由于某种原因你省略了完整的上下文:
使用dynamic_cast只能进行以下转换,...
1) ... 5) ...
6)当在构造函数或析构函数中使用dynamic_cast(直接或间接),并且表达式引用当前正在构造/销毁的对象时,该对象被认为是派生最多的对象。如果new_type不是指向构造函数/析构函数自己的类或其基础的指针或引用,则行为是未定义的。
由于您没有在构造函数或析构函数中使用它,因此案例6显然无关紧要。
与您的代码实际相关的案例是:
5)如果expression是多态类型Base的指针或引用,并且new_type是Derived类型的指针或引用,则执行运行时检查:
a)检查由表达式指向/识别的最派生的对象。如果在该对象中,表达式指向/指向Derived的公共基础,并且如果只有一个派生类型的子对象是从由表达式指向/标识的子对象派生的,则转换结果/指向该派生子对象。 (这被称为“垂头丧气”。)
b)否则,如果表达式points /引用最派生对象的公共基础,并且同时,最派生的对象具有Derived类型的明确公共基类,则转换点的结果/指的是Derived(This被称为“侧播”。)c)否则,运行时检查失败。如果在指针上使用dynamic_cast,则返回new_type类型的空指针值。如果它在引用上使用,则抛出异常std :: bad_cast。
检查以后编辑的代码:
ActorComponent(ActorComponent* parent) {
// using `getParent` inside the constructor:
// `int` obviously isn't base of the ActorComponent
auto p = this->getParent<int>();
}
第6条第一部分的条件
当dynamic_cast用于构造函数或析构函数(直接或间接)时......
满足(getParent
代码间接在构造函数中),但第二部分:
...和表达指的是当前正在建设/破坏的对象......
不满意,因此第6条仍然不适用。
你正在施放m_parent
,它是你正在构建的ActorComponent
对象的成员子对象。由于成员子对象是在您进入构造函数体时完全构造的,因此该对象未被构造,并且我们不在该对象的构造函数中。除了其他任何东西,该对象(m_parent
)是一个指针,它没有构造函数。顺便说一句,它是未初始化的,所以你的代码完全是非法的,但不是因为你问的原因。
以上是关于确保dynamic_cast不会导致未定义的行为C ++的主要内容,如果未能解决你的问题,请参考以下文章
何时在空实例上调用成员函数会导致 C++11 中的未定义行为? [复制]