[英]C++ - Change private member from outside the class
Is this code causes undefined behavior? 此代码是否会导致未定义的行为? Or can i run into a problem with this?
还是我会遇到这个问题? (copy the full class without functions, just variables with public modifier and modify the private memebers throw this pointer) example:
(复制没有函数的完整类,仅复制带有public修饰符的变量,并修改私有成员抛出该指针)示例:
#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;
}
output: 输出:
(4, 5)
(1, 2)
(with the original member order, of course) (当然有原始的会员订单)
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 1 . 尽管您的类与布局兼容(请参见下文),但是由于C ++严格的别名规则 1禁止此类指针强制转换,因此代码仍表现出未定义的行为。
But: replacing the casts with a union
makes the code standard-compliant; 但是:用
union
替换强制类型转换使代码符合标准; this is actually guaranteed to work in C++11: 实际上保证可以在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 classes 2 (C++11, §9 ¶7), and share a "common initial subsequence" (§9.2, ¶20); 这是因为
Point
和PointHack
是标准布局类2 (C ++ 11,§9¶7),并共享“公共初始子序列”(§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 . 这样,如果它们都存储在同一个联合体(在此为
pu
)中,则可以“检查其中任何一个的公共初始部分” 3 。
Still, this answer is mostly an exercise of style; 不过,这个答案主要是一种风格的练习。 don't exploit such tricks unless you are really forced to.
除非您真的被迫使用,否则不要利用这些技巧。 C++ provides better means to access private members if necessary without brutally breaking the encapsulation - you have getters/setters, protected inheritance, friend classes, ... And in general, if you access private class members in ways not intended by your target class, you are potentially violating the assumptions of that class about how its data is modified, which can lead to erratic behavior of the code of its methods.
C ++在必要时提供了更好的方法来访问私有成员,而又不会残酷地破坏封装-您具有吸气剂/设置器,受保护的继承,朋友类……而且通常,如果您以目标类不希望的方式访问私有类成员,您可能违反了该类关于如何修改其数据的假设,这可能导致其方法代码的行为不稳定。
Notes: 笔记:
ph
makes it the "active object" of the union
, and then p.Print()
is the one "inspecting" the "inactive" object. ph
使其成为的“活动对象” union
,然后p.Print()
是“检查”所述“不活动”对象中的一个。 Yes, the posted code invokes undefined behavior. 是的,发布的代码会调用未定义的行为。 Don't do that.
不要那样做
If you want to see a really insane way that some people accomplish this unsavory goal, here you go: access private member using template trick 如果您想以某种疯狂的方式实现某些人完成这个不愉快的目标的方法,请执行以下操作: 使用模板技巧访问私有成员
But really, don't do that. 但实际上,不要那样做。
PS: never use C-style casts in C++. PS:切勿在C ++中使用C样式的强制转换。 Use static_cast, dynamic_cast, reinterpret_cast, and const_cast, as appropriate.
根据需要使用static_cast,dynamic_cast,reinterpret_cast和const_cast。 C-style casts are needlessly unsafe.
C样式的强制转换不必要地是不安全的。
i found the problem 我发现了问题
/*code:*/
#include <stdio.h>
void check(short *h,long *k)
{
*h=5;
*k=6;
if (*h == 5)
printf("strict aliasing problem\n");
}
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/
*/
(same as in c++) (与c ++中相同)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.