从基础 class 转换为派生基础时到底发生了什么?
What happens exactly when casting from a base class to derived one?
在下面的代码中,为什么编译器同意将基数 class 转换为派生的 class 并且知道该对象纯粹是基数?尽管 print2() 是派生函数,但如何调用它?你能告诉我从 compiler/memory 经理的角度来看到底发生了什么吗?
#include <iostream>
using namespace std;
class Base {
public :
virtual void print(){
cout << "Hello from Base" << endl;
}
};
class Derived : public Base {
public:
void print(){
cout << "Hello from Derived" << endl;
}
void print2(){
cout << "Print2" << endl;
}
};
int main()
{
Base * b = new Base();
Derived * d = static_cast<Derived *>(b);
d -> print2();
}
这是未定义的行为,不需要诊断。
编译器没有义务为每个可能的编程错误报告编译错误。唯一需要的诊断是当程序格式错误时。
static_cast
本身在技术上没有任何问题,仅凭该声明。它遵循所有必要的规则。它使用不当以及由于较早的语句导致未定义行为的事实不需要来自编译器的错误消息。 new
语句和 static_cast
本身可以在完全独立的 .cpp
文件中(中间有一个函数调用,一个函数调用 new,并将结果作为参数传递给函数在执行 static_cast
的另一个 .cpp
文件中)。这在逻辑上与显示的代码相同。编译器在编译另一个 .cpp
文件时怎么可能报告错误,并且不知道第一个文件中发生了什么?
的确,某些编译器可能能够检测到此错误并发出警告消息(可能仅在启用某些优化级别的情况下),但没有义务这样做。
在下面的代码中,为什么编译器同意将基数 class 转换为派生的 class 并且知道该对象纯粹是基数?尽管 print2() 是派生函数,但如何调用它?你能告诉我从 compiler/memory 经理的角度来看到底发生了什么吗?
#include <iostream>
using namespace std;
class Base {
public :
virtual void print(){
cout << "Hello from Base" << endl;
}
};
class Derived : public Base {
public:
void print(){
cout << "Hello from Derived" << endl;
}
void print2(){
cout << "Print2" << endl;
}
};
int main()
{
Base * b = new Base();
Derived * d = static_cast<Derived *>(b);
d -> print2();
}
这是未定义的行为,不需要诊断。
编译器没有义务为每个可能的编程错误报告编译错误。唯一需要的诊断是当程序格式错误时。
static_cast
本身在技术上没有任何问题,仅凭该声明。它遵循所有必要的规则。它使用不当以及由于较早的语句导致未定义行为的事实不需要来自编译器的错误消息。 new
语句和 static_cast
本身可以在完全独立的 .cpp
文件中(中间有一个函数调用,一个函数调用 new,并将结果作为参数传递给函数在执行 static_cast
的另一个 .cpp
文件中)。这在逻辑上与显示的代码相同。编译器在编译另一个 .cpp
文件时怎么可能报告错误,并且不知道第一个文件中发生了什么?
的确,某些编译器可能能够检测到此错误并发出警告消息(可能仅在启用某些优化级别的情况下),但没有义务这样做。