dynamic_cast“this”到派生类型:什么时候合法?

时间:2015-04-29 14:13:55

标签: c++ inheritance dynamic-cast downcast

这是一个显然不起作用的代码,因为在构造函数中向下转发“this”是非法的:

#include <cassert>

class A {
protected:
        virtual ~A() {}
public:
        A();
};

class B : public A {
};

A::A() {
        assert(dynamic_cast<B*>(this));
}

int main(void) {
        B b;
        return 0;
}

正如所料,当使用g ++编译时,断言失败。

这是另一个代码,但是,有效(至少使用g ++ 4.7,我还没有尝试过其他编译器):

#include <cassert>

class A {
protected:
        virtual ~A() {}
public:
        A() {}
        void f();
};

class B : public A {
public:
        B() {
                f();
        }
};

void A::f() {
        assert(dynamic_cast<B*>(this));
}

int main(void) {
        B b;
        return 0;
}

我的问题是:第二个代码是“合法的”,即我可以期望任何编译器都可以这样工作吗?

我的直觉是,因为从B的构造函数的主体调用f(),所以“b”已经很好地形成为类型B的实例,这使得代码合法。然而,我仍然有点像构造函数那样动态播放“this”......

(请注意,我的问题不在于这是否是好的做法,只要它是合法的。)

2 个答案:

答案 0 :(得分:4)

是的,第二个例子定义明确,演员表会成功。在B的构造函数期间,对象的动态类型为B,因此对B*的强制转换将成功。

在第一个示例中,正如您所说,在A的构造函数中,动态类型为A,因此对B*的强制转换将失败。

答案 1 :(得分:1)

  

我的问题是:第二个代码是“合法的”

是的,没关系。

  

我的直觉是,因为f()是从B的构造函数的主体调用的,所以“b”已经很好地形成为B类的实例,这使得代码合法

无论如何它是 legal ,但这就是断言成功而不是失败的原因:当你进入B body 时构造函数,您有一个类型B

的实例
  

然而,我仍然有点像构造函数那样“动画”这个......

请注意A::f 静态格式正确格式良好 - 无论您从哪里调用它 - 如果从A::A调用,它只会动态使断言失败。您还可以实例化A并直接在其上调用f(因为A不是抽象的) - 这仍然是格式良好的,但会使断言失败。