直到今天,我还以为如果我的类AB没有任何关联,那么使用指针的dynamic_cast将无法返回nullptr。现在我读到这会导致不确定的行为...

cppreference - dynamic_cast:



我有这样的代码:

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 很好。由于某种原因,您在显然不适用于您的代码的条件下选择了代码。

    您的报价:



    显然是关于在构造函数或析构函数中使用dynamic_cast的信息,尽管出于某些原因,您省略了完整的上下文:



    由于您没有在构造函数或析构函数中使用它,因此情况6显然无关紧要。

    与您的代码实际相关的情况是:




    检查稍后编辑的代码:

    ActorComponent(ActorComponent* parent) {
        // using `getParent` inside the constructor:
        // `int` obviously isn't base of the ActorComponent
        auto p = this->getParent<int>();
    }
    

    第6条的条件的第一部分



    被满足(getParent代码在构造函数中间接存在),但是第二部分:



    不满意,因此第6条仍然不适用。

    您正在转换m_parent,它是您正在构造的ActorComponent对象的成员子对象。由于成员子对象是在您进入构造函数的主体时完全构造的,因此该对象未被构造,并且我们不在该对象的构造函数中。除了其他内容外,该对象(m_parent)是一个指针,没有构造函数。顺便说一句,它是未初始化的,因此您的代码无论如何都是完全非法的,但并非出于您询问的原因。

    关于c++ - 确保dynamic_cast不会导致未定义的行为C++,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49038905/

    10-11 19:03