C++ 的 class 没有虚函数表的时候,和 C 的 struct 在内存布局上没什么区别,这个时候 int* add = (int*)&t; 这里把取 t 的地址,这个地址指向的内存位置刚哈就是放第一个成员变量 int num 。因此你再强转成 int* 就得到了 num 的指针。然后对这个指针赋值,就修改了 num 的值。
如果 C++ 的 class ,没有构造函数、没有析构函数、也没有虚函数表,那么有一个专有名词来称呼它: Plain Old Data, 也就是所谓的 POD 类型。当你需要跟很多 系统 API, 或者 C API 交互的时候,你总是会定义一些这样的 POD 类型,因为那些 API 接受的就是 C 的 struct 内存布局的对象的指针。
此外,在 C++ 里面,语言提供给了程序员【自由的解释内存权限】,也就是,一个指针指向的内存,到底是什么,程序员自己在基于对 C++ 规范定义的内存规则的理解下,可以自由地将内存地址转成 void* 指针,然后你自己知道它是什么类型,传递到别的地方,那个地方再强转成你知道的正确的类型的指针。这往往会在一些需要传入不同类型指针的地方用到。C++ 为了规范,还提供了与此相关的转换函数有一组:static_cast, dynamec_cast, const_cast, reinterpret_cast。简单说,进入指针的世界,实际上就是你(程序员)自己决定你的代码是否对,当然如果不对,程序运行时你会获得一堆运行时异常。
当然,一般来说,先别这么干,先用有类型的,常规的规则去写代码总是好的,因为基于隐式规则写的代码,你需要文档其他人才好读,毕竟程序员 70% 的时间是在读代码。
推荐阅读《深入C++对象模型》这本书。