派生类型的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;
}
我的问题是:第二个代码是否"合法",即我可以期望对于任何编译器来说,它会以这种方式工作吗?
我的直觉是,由于 f() 是从 B 的构造函数的主体中调用的,因此 "b" 已经很好地作为类型 B 的实例进行了格式化,这使得代码合法。然而,我仍然有点从构造函数中dynamic_casting"这个"......
(请注意,我的问题不是这是否是好的做法,只是它是否合法)。
是的,第二个示例定义良好,强制转换将成功。在B
的构造函数中,对象的动态类型是B
的,所以强制转换为B*
将成功。
第一个示例中,正如您所说,在 A
的构造函数中,动态类型是 A
,因此强制转换为 B*
将失败。
我的问题是:第二个代码"合法"吗
是的,没关系。
我的直觉是,由于 f() 是从 B 的构造函数的主体调用的,因此"b"已经很好地作为类型 B 的实例,这使得代码合法
无论如何,这是合法的,但这就是断言成功而不是失败的原因:当你进入B
构造函数的主体时,你有一个类型 B
的实例
然而,我仍然有点dynamic_casting构造函数的"这个"......
请注意,无论您从何处调用A::f
,它都是静态格式良好的 - 如果从 A::A
调用,它只会动态失败断言。您还可以实例化一个A
并直接在其上调用f
(因为A
不是抽象的) - 这仍然是格式良好的,但会使断言失败。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 派生类型的dynamic_cast "this":什么时候合法?
- 什么时候应该使用指针或引用成员,什么时候应该在Qt中传递nullptr或this作为父指针
- 什么时候在 lambda 中捕获'this'?
- 什么时候在构造函数和析构函数中调用 this-> 是安全的