在调用析构函数

时间:2017-04-20 13:13:43

标签: c++

我知道虚拟表会在调用类析构函数之前自动更新,所以我想到了检查对象类型信息会发生什么。我写了这个例子:

#include <iostream>

class Base {
public:
    Base(std::function<void(Base*)> callback) : _callback(callback) {}

    virtual ~Base() {
        _callback(this);
    }

    std::function<void(Base*)> _callback;
};

class Derived : public Base {
    using Base::Base;
};
int main() {
    auto check_type = [](Base* item) {
        if (dynamic_cast<Derived*>(item)) {
            std::cout << "is derived" << std::endl;
        } else {
            std::cout << "no derived" << std::endl;
        }
    };

    Derived derived(check_type);
    check_type(&derived);

    return 0;
}

并基于输出:

is derived
no derived

似乎clang-802.0.41更新了此记录。现在我想知道这是标准化的还是编译器特定的?

2 个答案:

答案 0 :(得分:3)

使用dynamic_cast在构造函数或析构函数中不起作用。在Base::Base期间,您还没有执行派生类型的构造函数。同样,到达Base::~Base时,派生类型的析构函数必须已经完成。在这两种情况下,您的实例都不是有效的Derived对象。

来自http://en.cppreference.com/w/cpp/language/dynamic_cast#Explanation

  

6)当在构造函数或析构函数中(直接或间接)使用dynamic_cast时,表达式引用当前正在构造/销毁的对象,该对象被认为是派生最多的对象。 如果new_type不是构造函数/析构函数自己的类或其基础之一的指针或引用,则行为未定义。

答案 1 :(得分:0)

class.cdtor 15.7中:

  

如果dynamic_cast的操作数引用了下面的对象   构造或破坏以及操作数的静态类型不是   指向构造函数或析构函数自己的类或对象的指针   作为其基础之一,dynamic_cast导致未定义的行为。

this不是指向Base自己的类的指针,也不是指向其中一个基础的指针,因此您有未定义的行为。