Despite your classes being layout compatible (see below), your code exhibits undefined behavior due to the fact that such pointer casts are prohibited by the C++ strict aliasing rules https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule1.
但是:用union
使代码符合标准;这实际上保证可以在 C++11 中工作:
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
void Print() {
cout << "(" << x << ", " << y << ")" << endl;
}
};
struct PointHack {
int x;
int y;
};
union pu
{
Point p;
PointHack ph;
pu(int x, int y) : p(x, y) {}
};
int main() {
pu u(4,5);
u.p.Print();
u.ph.x=1;
u.ph.y=2;
u.p.Print();
return 0;
}
This comes from the fact that Point
and PointHack
are standard-layout classes2 (C++11, §9 ¶7), and share a "common initial subsequence" (§9.2, ¶20); as such, if they both are stored in the same union (here pu
) it's permitted to "inspect the common initial part of any of them"3.
不过,这个答案主要是一种风格练习。除非迫不得已,否则不要利用这些技巧。 C++ 提供了更好的方法来在必要时访问私有成员,而不会残酷地破坏封装 - 你有 getter/setter、受保护的继承、友元类……一般来说,如果你以目标类不希望的方式访问私有类成员,您可能违反了该类关于如何修改其数据的假设,这可能会导致其方法代码的不稳定行为。
Notes:
- 在 C++ 中,不能让两个不相关类型的指针指向同一个对象;此限制主要用于帮助优化器进行有关别名的假设。
- 请注意,这方面的要求相当严格;通常,大多数基本上不是 C 结构的类不符合此条件。即使具有不同的访问限定符也可能会破坏魔法。
- 这个想法是分配给
ph
使其成为“主动对象”union
, 进而p.Print()
是“检查”“非活动”对象的一个。