私人/受保护/公众如何影响ABI?

时间:2017-08-31 12:19:24

标签: c++ oop

我想要的是某些班级成员有时候private而其他班次public。这些成员应该可以被某些模块访问,而其他模块则无法访问。

对此课程进行成像:

class Foo {
public:
    ...
private:
    ...
protected:
    ...
internal:
    int x;
};

在模块X中,internal定义为:

#define internal public

并在模块Y中定义为:

#define internal private

所以真正的问题是标准是否可以接受这个技巧,或者它是否会以任何方式改变类(或其成员)的签名。

我知道friendPIMPL适用于此类工作,但friend会变得非常混乱和PIMPL的表现(间接和事实你无法内联)对于我正在处理的代码库是不可接受的。

2 个答案:

答案 0 :(得分:4)

这是ODR违规,因此会调用未定义的行为。 (参见basic.def.odr] /6.1“D的每个定义应由相同的令牌序列组成”)。

但是,一个常见的实现是public,private,protected对类布局没有影响,因此它可以工作。

你在薄冰上滑冰;没有什么可以阻止编译器将所有公共成员放在第一位,然后是受保护的成员,然后是私有成员。更重要的是,一般来说,声明的顺序必须是内存中的顺序,所以

struct T {char a; int b; char c};

必须包含a,然后是b,然后是c。这是为了确保C兼容性。但是,对具有不同访问权限的元素的排序没有要求(参见[class.mem] /9.2 p13:“具有相同访问控制(第11章)的(非联合)类的非静态数据成员被分配,以便后来的成员在一个类对象中有更高的地址。具有不同访问控制的非静态数据成员的分配顺序是未指定的(第11条)“。所以给定

struct T {char a; int b; private: char c};

编译器可以对成员进行重新排序,并将c放在ab之间。

EJP和其他认为这些声明不是定义的人的最后说明:我已经给出了T以上的两个定义; 声明看起来像struct T;

编辑:感谢Fanael来自标准的引用。

答案 1 :(得分:0)

C ++最初似乎认为私有成员可以放在公共成员旁边的某个地方,也许这样他们可能是硬件中的受保护区域,因此可以想象公共和私人部分可以相对于每个部分移动其他。

可以在不使用Herb Stutter GOTW 76的技巧重新定义公共/私人的情况下测试您的代码,并在此处使用此数据完成功能完整的系统litb safer private member access

给出如下课程......

struct A {
  A(int a):a(a) { }
private:
  int a;
};

需要强盗类......

template<typename Tag, typename Tag::type M>
struct Robber { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

允许多次抢断的实用程序类......

template<typename Tag, typename Member>
struct TagBase {
  typedef Member type;
  friend type get(Tag);
};

宣布盗窃意图成为

struct A_f : TagBase<A_f, int A::*> { };
template struct Robber<A_f, &A::a>;

然后窃取数据......

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}