【问题描述】:

不幸的是,我有一个基本的 C++ 问题让我感到困惑。最近我遇到了一篇文章,它使用向下转换来访问使用向​​下转换的类的私有成员。我的问题是它为什么有效?

鉴于我有一个父类 P,它有一个 dummy* 类型的私有成员 m_p,那么使用的方法是创建一个 hack 类 hackP,如下所示:

class hackP: public P {
public:
dummy *m_p;
};

显然可以使用类似 sn-p 的代码访问 class P 私有成员 m_p

P parent = ...;
hackP *hp = (hackP*)&parent;
// access parent m_p as hp->m_p

任何帮助将不胜感激。

【问题讨论】:

  • 嗯,m_p 是公开的吗?有什么技巧?
  • 您可以通过使 hackP 不从 P 继承来做到这一点,只要 HP 和 P 之间的类使用该类型转换完美对齐(不是一个好主意)。但是继承部分让我感到困惑,因为这应该改变内存中的签名足以打破它。
  • 除了代码中的错误(正如@MichaelDorgan 提到的,不应该有继承)这是未定义的行为。因此,就标准而言,它起作用的唯一原因是纯属运气
  • @PaulTarr:你有这篇文章的链接吗?我认为翻译中丢失了一些东西。
  • GotW #76 似乎相关:gotw.ca/gotw/076.htm

标签: c++ class private member undefined-behavior


【解答1】:

看起来 GotW #76 Uses and Abuses of Access Rights 很好地涵盖了这个主题,我不得不说我从中找到了一些我不知道的有趣的花絮。

这篇文章Access to private members. That's easy! 费了些力气,但看起来更灵活。

来自这个线程Is private member hacking defined behaviour? 的这个answer 非常相似但不相同,这似乎表明这是未定义的行为,因为不能保证 access-qualifier 部分之间的布局相同。从draft C++ standard9.2 部分 Class members 说(强调我的):

<1234565>

具有相同访问权限的(非联合)类的非静态数据成员 控制权(第 11 条)被分配,以便后来的成员拥有更高的 类对象中的地址。 非静态的分配顺序 未指定具有不同访问控制的数据成员 (11)。

【问题讨论】:

  • 非常感谢引用 GotW #76 和私有成员黑客定义的行为。尤其是后者。我只需要用我的编译器尝试破解,看看会发生什么,因为我正在使用提供的 dll 并且无法重新编译它。感谢您的回复。