在下面的main
函数中,第一个static_cast
有效,因为我正在尝试将(基类引用Derived1
类)转换为派生引用
但是为什么第二次使用值进行转换打印,虽然它打印d2.y
的垃圾值,我认为它应该是警告或编译错误。
如何基础引用基础对象选择派生类的值(在这种情况下为d2.y
,我也可以为其赋值)
有人可以解释这两种情况会发生什么。
class Base1
{
public:
Base1()
{
x = 999;
}
int x;
};
class Derived1: public Base1
{
public:
Derived1()
{
y = 1000;
}
int y;
};
int main()
{
Derived1 d;
std::cout << d.x << " " << d.y << std::endl;
Base1& b = d;
Base1 b1;
Base1 & b2 = b1;
Derived1& d1 = static_cast<Derived1&>(b);
Derived1& d2 = static_cast<Derived1&>(b2);
std::cout << d1.x << " " << d1.y << std::endl;
std::cout << d2.x << " " << d2.y << std::endl;
return 0;
}
答案 0 :(得分:3)
static_cast
是您对编译器的承诺,即基类确实是派生类 - 不需要计算机进行双重检查。你告诉编译器你作为程序员知道编译器不知道哪些东西可以保证这是真的。因此,当指令要求CPU访问派生类型成员所在的内存地址的值时,它会进入一些可以包含任何内容的内存,就像你告诉它一样。
除非非常简单的情况,编译器无法知道对基类型的引用究竟是什么。这就是dynamic_cast存在的原因(但它需要额外的信息 - vtable - 以便检查)。
如果两个类型不可能相关, static_cast
将导致编译时错误,但如果它们在同一个继承链中,则可以使用无效的static_cast
执行各种错误。
当您开始考虑将C / C ++类型简单地定义为内存中的偏移时,许多行为和语法要求开始变得更有意义。