2017-08-31 4 views
2

私が欲しいのは、一部のクラスメンバーのために時々privateと他の時間がpublicになることです。これらのメンバーは、いくつかのモジュールからアクセス可能であり、他のメンバーがアクセスできないと考えられています。私的/保護/公衆がABIにどのような影響を与えますか?

イメージングこのクラス:internal Xモジュールで

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

は次のように定義されます

#define internal public 

およびモジュールYで、それは次のように定義されています:

#define internal private 

だから、本当の問題をこのトリックが標準で受け入れ可能かどうか、またはクラスの署名を変更するかどうかです(またはどのようにしても、

は私がfriendPIMPLは、ジョブのこの種のですが、friendは非常に厄介取得することができますし、PIMPLのパフォーマンス(間接およびインラインすることができないという事実は)私が働いているコードベースのために受け入れられないことを知っていますに。

+9

はODR違反したがってUBのように聞こえます。おそらくUBはあなたが望むことをします。 – nwp

+2

メンバーの可視性は、生成されたコードに渡されず、ABIには影響を与えません。また、ABIの影響を受けます。 –

+2

'internal'マクロについては、その目的は何ですか?どのような問題が解決するはずですか?ユースケースや要件、またはこれにつながるデザインがありますか?これには[XY問題](http://xyproblem.info/)の匂いがあります。おそらく、あなたの要件やデザインを見直す時間ですか?また、「モジュール」はリンクされて同じプログラムの一部を構成しますか? –

答えて

4

違反のため、未定義の動作が発生します。 (basic.def.odrも参照)/6.1 "Dの各定義はトークンの同じシーケンスからなるものとする")。

しかし、一般的な実装では、public、private、protectedはクラスレイアウトに影響を与えないので動作します。

あなたは薄い氷の上にスケートしています。コンパイラがすべてのパブリックメンバを最初に配置し、次に保護されたものをプライベートなものに置き換えることは何もありません。点より、一般的に、宣言の順序はそれほど

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

メモリ順序であることが要求されるc次いで、b次いで、aが要求されます。これはCの互換性を保証するためです。ただし、アクセスが異なる要素の順序付けに関する要件はありません([class.mem] /9.2 p13を参照)。同じアクセス制御(11節)を持つ(非ユニオン)クラスの非静的データメンバーは、後のメンバーは、クラスオブジェクト内の上位アドレスを持っている。異なるアクセス制御と非静的データメンバの割り当ての順序が指定されていない(第11条)」。だから、

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

与え、コンパイラはメンバーを並べ替えるとcを置くことができますabの間の隙間にある。

最後の挨拶は、EJPであり、これらは宣言ではなく、宣言である:私は2つのの定義T上記; の宣言struct T;のようになります。

編集:標準から引用するとFanaelに感謝します。

+2

これは正しいです。[basic.def.odr] /6.1も参照してください。 "Dの各定義はトークンの同じシーケンスで構成されます。 1つのTUでは 'internal'が' public'で、もう1つの 'TU'では' private'が明らかに違反しています。 – Fanael

+0

私はC++が明示的にコンパイラの並べ替えを禁止していると思っていました。 – nwp

+1

@nwp:同じアクセス制御(11節)を持つ(非ユニオン)クラスの非静的データメンバーには、 が割り当てられ、後のメンバーはクラスオブジェクト内でより高いアドレスを持ちます。静的データ 異なるアクセス制御のメンバーが不特定(11節) " –

0

C++はもともと、プライベートメンバーがパブリックメンバーの次の場所以外に置かれる可能性があると考えていました。おそらく、ハードウェアの保護された領域になる可能性があるためです。お互い。次のようにクラスを考えると、このデータと

ハーブスタッターで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; 
    } 
}; 

複数の盗みを許可するユーティリティクラス....

盗難の意図は、データを盗む

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

なる宣言

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

....

int main() { 
    A a(42); 
    std::cout << "proof: " << a.*get(A_f()) << std::endl; 
} 
関連する問題