C++ - 从类外部更改私有成员

2024-03-27

这段代码会导致未定义的行为吗?或者我可以遇到这个问题吗? (复制没有函数的完整类,只是带有公共修饰符的变量并修改私有成员抛出此指针) 例子:

#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)

(当然还有原来的会员订单)


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:

  1. 在 C++ 中,不能让两个不相关类型的指针指向同一个对象;此限制主要用于帮助优化器进行有关别名的假设。
  2. 请注意,这方面的要求相当严格;通常,大多数基本上不是 C 结构的类不符合此条件。即使具有不同的访问限定符也可能会破坏魔法。
  3. 这个想法是分配给ph使其成为“主动对象”union, 进而p.Print()是“检查”“非活动”对象的一个​​。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ - 从类外部更改私有成员 的相关文章

  • 在 C/C++ 中读取和写入二进制文件的中间部分

    如果我有一个大的二进制文件 假设它有 100 000 000 个浮点数 C 或 C 有没有办法打开文件并读取特定的浮点数 而不必将整个文件加载到内存中 即我如何快速找出第 62 821 214 个浮点是什么 第二个问题 有没有办法更改文件中
  • 改变 RGB 颜色的色调

    我正在尝试编写一个函数来改变 RGB 颜色的色调 具体来说 我在 iOS 应用程序中使用它 但数学是通用的 下图显示了 R G 和 B 值如何随色调变化 看起来 编写一个函数来改变色调似乎应该是一个相对简单的事情 而不需要对不同的颜色格式进
  • IssuerSigningKeyResolver 调用异步方法

    我们使用 IssuerSigningKeyResolver 它是 Microsoft IdentityModel Tokens 的一部分 用于令牌验证并接受非异步委托 我们调用一个异步方法 这将导致阻塞调用 因此想知道使用它的正确方法是什么
  • 我是否必须使用我的数据库训练 Viola-Jones 算法才能获得准确的结果?

    我尝试提取面部数据库的面部特征 但我认识到 Viola Jones 算法在两种情况下效果不佳 当我尝试单独检测眼睛时 当我尝试检测嘴巴时 运作不佳 检测图像的不同部分 例如眼睛或嘴巴 或者有时会检测到其中几个 这是不可能的情况 我使用的图像
  • 在 Eclipse 4.4.2 中使用 C 代码中的构建变量

    我有一个之前使用 Eclipse 3 5 2 创建的项目 在其中 我能够在项目属性中设置构建变量 在这种情况下 假设我设置了SW VERSION是 4403 现在这应该是一个十六进制数字 所以在构建设置中 我添加了一个符号 VERSION
  • 单击按钮本地化应用程序

    我在我的项目 mainMaster 页面中找到了 imageButtons
  • 如何将文本框中删除的字符替换为0

    在winforms中 如何用零替换删除的字符 例如 文本框中为 12 45 如果我们删除小数点后 它应该变成12 00 同样的方法删除前面的000 45 默认值应为 000 00 Use a 蒙版文本框 http msdn microsof
  • 字符串中unicode字符的正则表达式

    我正在使用 C 进行一些 OCR 工作 并提取了我需要使用的文本 现在我需要使用正则表达式解析一行 string checkNum string routingNum string accountNum Regex regEx new Re
  • C 中经过的时间

    include
  • 无效的跨线程访问问题

    我有两个 ViewModel 类 PersonViewModel 和 PersonSearchListViewModel PersonViewModel 实现的字段之一是通过 WCF 下载的个人资料图像 本地缓存在独立存储中 PersonS
  • 是否可以在三元表达式上只放置一个选项?

    我只是好奇这是否可能 或者是否有办法使它成为 C 的有效语法 expression value do nothing here or put some empty block like SomeClass SomeMethod Edit 为
  • 如何检测机器是否加入域?

    如何检测计算机是否已加入 Active Directory 域 相对于工作组模式 如果没有必要的话 不要用 pinvoke 来愚弄 参考System DirectoryServices 然后调用 System DirectoryServic
  • 最好的 C++ 编译器是哪个? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 C 或 C++ 中使用逗号作为宏名称

    我想做这样的事情 define define MAX 10 000 000 undef 有什么技巧可以做到吗 编辑 我知道 C 14 中的数字分隔符 我正在寻找一种技巧来对不兼容的编译器执行相同的操作 EDIT2 请考虑Variadic M
  • C memcpy 二维数组

    我正在尝试使用将一个二维数组复制到另一个memcpy 我的代码 include
  • 如何使用 Xamarin 应用程序开发自动注销

    我必须在 App xaml cs 上添加功能才能使其正常工作 我在 OnStart 上添加了功能 但现在它会间歇性地一次又一次地将我从应用程序中注销 根据下面的代码 我需要做什么才能让它停止这样做 或者我的代码有问题 这是我最新的代码 na
  • 类型“MyApp”已包含“MystatusBar”的定义

    我的应用程序 XAML
  • 在源代码和预编译二进制文件之间切换

    我们的应用程序中有大量的库 库是用 C 或 C 编写的 平台 net Framework Windows 64 位 将所有内容编译为源代码需要花费大量时间 我们正在考虑切换到预构建的二进制文件 但我们仍然希望保留返回源代码的可能性 作为版本
  • 如何在 MVC 5 中设置自定义 ClaimsPrincipal?

    我创建了一个自定义主体类 public class FacebookPrincipal ClaimsPrincipal public JObject Data get set 我想用它 当用户登录时 我尝试设置 var fbP new Fa
  • 如何包装实体框架以在执行前拦截 LINQ 表达式?

    我想在执行之前重写 LINQ 表达式的某些部分 我在将重写器注入正确的位置时遇到问题 实际上根本没有 查看实体框架源代码 在反射器中 它最终归结为IQueryProvider Execute在 EF 中 它通过以下方式耦合到表达式Objec

随机推荐