为何reinterpret_cast未创建对象却能转换指针并调用类方法?
问题分析:reinterpret_cast转换指针后调用成员函数的异常现象
测试代码
#include <iostream> using namespace std; class Mango { public: Mango() { cout<<"mango called"<<endl; } void print() { cout<<"mango"<<endl; } }; class Apple { public: Apple() { cout<<"apple called"<<endl; } void print() { cout<<"apple"<<endl; } }; int main(int argc, char* argv[]) { Mango* m = new Mango(); Apple* a = reinterpret_cast<Apple*>(m); a->print(); return 0; }
运行输出
mango called apple
问题核心
通过指针a调用print()方法输出了"apple",但Apple类的构造函数从未被调用,即未创建Apple对象。请问这一现象为何会发生?指针a未指向已创建的Apple对象,为何能实现此调用?它不是应该指向Mango对象的内存数据吗?
解答
这事儿的核心在于非虚成员函数是编译期绑定,再加上reinterpret_cast的“粗暴转换”特性:
非虚成员函数的调用逻辑是编译时就定死的:编译器只看指针的静态类型(也就是代码里写的
Apple*),不管它实际指向什么。a被声明成Apple*,所以编译器直接把a->print()翻译成调用Apple::print(),根本不会在运行时去检查指针实际指向的对象类型。reinterpret_cast就是个“二进制强转工具”:它不管类型是否兼容,直接把Mango*的内存地址原样当成Apple*用,既不会帮你创建Apple对象,也不会做任何类型校验。这里Mango和Apple都没有成员变量,所以那块内存里啥数据都没有,但也不影响调用。为啥调用没崩溃?因为
print()没用到对象的任何数据——这类不带成员变量访问的非虚函数,本质上和全局函数差不了多少,只是多了个没用到的this指针。哪怕this指向的是Mango对象的内存,函数照样能跑,输出"apple"。但必须强调:这是C++标准明确的未定义行为!这次能正常输出纯属巧合,要是类里加了成员变量或者虚函数,大概率会崩溃、乱输出,甚至触发更诡异的问题,绝对不能在生产代码里这么写。
内容的提问来源于stack exchange,提问作者Shivanshu Arora
相关产品推荐
相关产品推荐

