这是一个显然不起作用的代码,因为在构造函数中向下转发“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”......
(请注意,我的问题不在于这是否是好的做法,只要它是合法的。)
答案 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
不是抽象的) - 这仍然是格式良好的,但会使断言失败。