想象一下这段代码:
class Base {
public:
virtual void foo(){}
};
class Derived: public Base {
public:
int i;
void foo() override {}
void do_derived() {
std::cout << i;
}
};
int main(){
Base *ptr = new Base;
Derived * static_ptr = static_cast<Derived*>(ptr);
static_ptr->i = 10; // Why does this work?
static_ptr->foo(); // Why does this work?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么我在控制台上获得结果10?我想知道因为我认为ptr是指向基础对象的指针.因此,该对象不包含int i或方法do_derived().是否自动生成了一个新的derived-Object?
当我do_derived()在Base类中声明一个虚方法时,会选择这个,但为什么呢?
Snp*_*nps 25
int* i = new int{1};
delete i;
std::cout << *i << std::endl;
Run Code Online (Sandbox Code Playgroud)
如果工作的定义是代码将编译和执行,那么这也将"起作用".
但是,它显然是未定义的行为,并且无法保证可能发生的情况.
在您的情况下,代码编译为static_cast不执行任何检查,它只是转换指针.访问尚未分配和初始化的内存仍然是未定义的行为.
正如评论中所提到的,"恰好按照预期行事"与"作品"不同.
我们做一些修改:
#include <iostream>
#include <string>
class Base{
public:
virtual void foo(){
std::cout << "Base::foo" << std::endl;
}
};
class Derived: public Base{
public:
int a_chunk_of_other_stuff[1000000] = { 0 };
std::string s = "a very long string so that we can be sure we have defeated SSO and allocated some memory";
void foo() override {
std::cout << "Derived::foo" << std::endl;
}
void do_derived() {
std::cout << s << std::endl;
}
};
int main(){
Base *ptr = new Base;
Derived * static_ptr = static_cast<Derived*>(ptr);
static_ptr -> foo(); // does it though?
static_ptr -> do_derived(); // doesn't work?
static_ptr->a_chunk_of_other_stuff[500000] = 10; // BOOM!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
Base::foo
Process finished with exit code 11
Run Code Online (Sandbox Code Playgroud)
在这种情况下,没有一项操作符合我们的预期.分配到阵列导致了段错误.