可以通过强制转换为布局兼容类型来访问私有成员吗?

Tem*_*Rex 6 c++ casting access-control private-methods c++11

从这个问题的讨论如何在C++中实现私有变量的访问?我提出了一个变体:可以通过强制转换并依赖布局兼容性来调用私有成员函数,而不是访问私有数据成员吗?

一些代码(灵感来自Herb Sutter的列使用和滥用访问权限)

#include <iostream>

class X 
{ 
public:
  X() : private_(1) { /*...*/ }

private: 
  int Value() { return private_; }
  int private_; 
};

// Nasty attempt to simulate the object layout
// (cross your fingers and toes).
//
class BaitAndSwitch
    // hopefully has the same data layout as X
{   // so we can pass him off as one
public:
  int Value() { return private_; }
private:
  int private_;
};

int f( X& x )
{
  // evil laughter here
  return (reinterpret_cast<BaitAndSwitch&>(x)).Value();
}

int main()
{
    X x;
    std::cout << f(x) << "\n"; // prints 0, not 1
    return 0;
}; 
Run Code Online (Sandbox Code Playgroud)

注意:这有效(至少在Ideone上)!是否有任何方式的新的C++ 11标准给出了一个保证或至少一个实现定义方式通过依赖于布局的兼容性和的reinterpret_cast /的static_cast绕过访问控制?

EDIT1:输出Ideone

EDIT2:在Sutter的专栏中,他列出了上述代码无法保证工作的两个原因(虽然它在实践中有效)

a)X和BaitAndSwitch的对象布局不保证是相同的,尽管在实践中它们可能总是如此.

b)reinterpret_cast的结果是未定义的,尽管大多数编译器会让你尝试以黑客的意图使用结果引用.

新的C++ 11 Standard现在是否提供这些layout/reinterpret_cast保证?

Nic*_*las 3

是的,您可以创建一个与您试图窃取的类型使用相同布局的类型,然后reinterpret_cast从该类型转换为与您的布局兼容的类型。但这仅在以下情况下才受标准保护:当然,只有当它们的布局相同时,它才真正有效)。因此,如果源代码具有虚拟函数,那么您就完蛋了。

\n\n

这似乎满足了萨特的两个问题。标准布局的规则确保两种都是标准布局且以相同顺序定义相同成员的类型是布局兼容的(第 9.2 节,第 17 段):

\n\n
\n

如果两个标准布局结构(第 9 条)类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按声明顺序)具有布局兼容类型 (3.9),则它们是布局兼容的。

\n
\n\n

以及规则reinterpret_cast以及指定两种标准布局类型之间转换的含义的

\n\n
\n

对象指针可以显式转换为不同类型的对象指针。\n 当指向 T1\xe2\x80\x9d 的指针类型为 \xe2\x80\x9c 的纯右值 v 转换为类型为 \xe2\x80\x9c 的指针时cv T2\xe2\x80\x9d,结果为static_cast<cv T2*>(static_cast<cv void*>(v))如果 T1 和 T2 都是标准布局类型 (3.9),并且 T2 的对齐要求不比 T1 严格,或者任一类型为 void。

\n
\n

  • 这不违反严格的别名吗? (4认同)