C++ - 从类外更改私有成员
C++ - Change private member from outside the class
此代码是否会导致未定义的行为?或者我会遇到这个问题吗?(复制没有函数的完整类,只是带有公共修饰符的变量,并修改抛出此指针的私有模因(例:
#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;
};
int main() {
Point a(4, 5);
a.Print();
((PointHack *) (&a))->x = 1;
((PointHack *) (&a))->y = 2;
a.Print();
return 0;
}
输出:
(4, 5)
(1, 2)
(当然是原始会员订单(
尽管您的类与布局兼容(见下文(,但由于C++严格的别名规则1 禁止此类指针强制转换,您的代码表现出未定义的行为。
但是:用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;
}
这是因为Point
和PointHack
是标准布局类2(C++11,§9¶7(,并共享一个"公共初始子序列"(§9.2,¶20(;因此,如果它们都存储在同一个并集中(这里pu
(,则允许"检查其中任何一个的共同初始部分">3。
尽管如此,这个答案主要是一种风格的练习;除非你真的被迫这样做,否则不要利用这些技巧。C++提供了更好的方法来在必要时访问私有成员,而不会残酷地破坏封装 - 你有getter/setter,受保护的继承,友元类,...通常,如果您以目标类不打算的方式访问私有类成员,则可能会违反该类关于如何修改其数据的假设,这可能导致其方法代码的不稳定行为。
笔记:
- 在C++中,不能有两个不相关类型的指针指向同一个对象;此限制主要用于帮助优化器对别名进行假设。
- 请注意,对此的要求非常严格;通常大多数基本上不是 C 结构的类都不符合此条件。即使拥有不同的访问限定符也可以打破魔力。
- 这个想法是分配给
ph
使它成为union
的"活动对象",然后p.Print()
是"检查"非活动"对象的对象。
是的,发布的代码调用未定义的行为。 别这样。
如果你想看到一些人实现这个令人讨厌的目标的疯狂方式,你可以去: 使用模板技巧访问私人成员
但实际上,不要那样做。
PS:切勿在C++中使用C型转换。 根据需要使用static_cast、dynamic_cast、reinterpret_cast和const_cast。 C 型石膏不必要地不安全。
我发现了问题
/*code:*/
#include <stdio.h>
void check(short *h,long *k)
{
*h=5;
*k=6;
if (*h == 5)
printf("strict aliasing problemn");
}
int main(void)
{
long k[1];
check((short *)k,k);
return 0;
}
/*
$ gcc -Wall -ansi -pedantic -O0 -o o0 asd.c
$ ./o0
/output: nothing/
$ gcc -Wall -ansi -pedantic -O2 -o o2 asd.c
$ ./o2
/output: strict aliasing problem/
*/
(与 C++ 相同(
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 将公共但非静态的成员函数与ALGLIB集成
- 多成员Constexpr结构初始化
- 我们可以访问一个不存在的联盟的成员吗