如何用reinterpret_cast访问类S中的私有成员int i?
绕过类私有成员访问获取int成员的方法(附风险说明)
首先明确:这种绕过私有成员访问的操作属于C++标准中的未定义行为,完全依赖编译器的内存布局实现,实际项目中绝对不能使用——正确的做法是给类添加public的getter方法,或者将访问代码声明为类的友元。以下仅做技术探讨。
你之前的问题出在对std::string大小的误解上:sizeof(std::string("abcd"))等价于sizeof(std::string),因为std::string的大小是固定的(和存储的字符串长度无关,它内部用指针指向堆内存),但你可能没完成后续的指针转换,或者忽略了内存对齐的细节。
可行的两种实现方式
方式1:利用offsetof宏(仅适用于标准布局类)
你的类S没有虚函数,所有非静态成员的访问控制都是private,属于标准布局类,可以直接用offsetof宏获取成员的内存偏移量:
#include <iostream> #include <string> #include <cstddef> // 必须包含头文件才能用offsetof class S { std::string s = "abcd"; int i = 9; }; int main() { S s; // 访问std::string成员(你已实现的部分) auto* str_ptr = reinterpret_cast<std::string*>(&s); std::cout << "string成员值:" << *str_ptr << std::endl; // 获取int i的偏移并访问 size_t i_offset = offsetof(S, i); auto* int_ptr = reinterpret_cast<int*>(reinterpret_cast<char*>(&s) + i_offset); std::cout << "int i成员值:" << *int_ptr << std::endl; return 0; }
方式2:手动计算内存偏移
类的非静态成员会按声明顺序在内存中排列,且每个成员会自动对齐到自身的对齐要求。由于std::string的大小本身就是其对齐单位的倍数(比如64位系统下通常是24字节,对齐到8字节),所以int i的偏移量就是sizeof(std::string):
#include <iostream> #include <string> class S { std::string s = "abcd"; int i = 9; }; int main() { S s; // 访问std::string成员 auto* str_ptr = reinterpret_cast<std::string*>(&s); std::cout << "string成员值:" << *str_ptr << std::endl; // 计算偏移并访问int i char* class_base = reinterpret_cast<char*>(&s); auto* int_ptr = reinterpret_cast<int*>(class_base + sizeof(std::string)); std::cout << "int i成员值:" << *int_ptr << std::endl; return 0; }
关键风险提醒
- 未定义行为:C++标准不保证类的内存布局,编译器可以随意调整成员位置、添加填充字节,甚至在优化时直接移除未被public访问的私有成员。
- 跨平台/编译器兼容性差:不同架构(32/64位)、不同编译器(GCC/Clang/MSVC)下,
std::string的大小和内存对齐规则可能不同,代码无法移植。 - 违反封装原则:类的私有成员本就是为了隐藏实现细节,强行访问会破坏代码的可维护性和安全性。
内容的提问来源于stack exchange,提问作者Fluffle Puff
相关产品推荐
相关产品推荐

