dynamic_cast "this" 派生类型:什么时候合法?

dynamic_cast "this" to derived type: when is it legal?

这里的代码显然不起作用,因为在构造函数中向下转换 "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;
}

我的问题是:第二个代码是 "legal",也就是说,我是否可以期望任何编译器都能以这种方式工作?

我的直觉是,由于 f() 是从 B 的构造函数的主体中调用的,因此 "b" 已经作为类型 B 的实例得到了良好的构造,这使得代码合法。然而,我仍然有点 dynamic_casting "this" 来自构造函数...

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

是的,第二个例子定义好,转换成功。在 B 的构造函数中,对象的动态类型是 B,因此转换为 B* 将成功。

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

My question is: is the second code "legal"

是的,没关系。

My intuition is that since f() is called from the body of B's constructor, "b" is already well formed as an instance of type B, which makes the code legal

合法 无论如何,但这就是断言成功而不是失败的原因:当你在 bodyB 的构造函数中,您有一个 B

类型的实例

Yet, I'm still kind of dynamic_casting "this" from a constructor...

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