21

次のコードがあります。

struct A {
protected:
    A() {}

    A* a;
};

struct B : A {
protected:
    B() { b.a = &b; }

    A b;
};

奇妙なことにコンパイルされません。犯人はb.a = &b;割り当てです: GCC と clang の両方A()が保護されていると文句を言いますが、B は A を継承しているため、これは問題にはなりません。

4

4 に答える 4

21

の意味は、派生型は、任意のランダム オブジェクト*ではなく、独自のベースprotectedのメンバーにアクセスできるということです。あなたの場合、あなたの制御外にある のメンバーを変更しようとしている(つまり、 を設定できますが、 はできません)bthis->ab.a

興味がある場合は、これを機能させるためのハックがありますが、より良い解決策は、コードをリファクタリングし、ハックに依存しないことです。たとえば、引数として受け取るコンストラクターを提供しA(A*このコンストラクターは public である必要があります)、次の初期化子リストで初期化できますB

A::A( A* p ) : a(p) {}
B::B() : b(&b) {}

* protected独自の型のインスタンスまたは独自の型から派生したインスタンスの基本メンバーへのアクセスを許可します。

于 2012-09-04T20:38:00.640 に答える
2

ここには、実際には 2 つの別個の問題があります。

1 つ目は、行が割り当てを行うだけでなく、基本クラス (正常に動作します) と member を初期化しようとすることbです。bメンバーを作成するには、それを構築する必要があり、メンバーとしてコンストラクターにアクセスする必要がpublicありますが、それはありません。

次に、割り当ても非パブリックメンバーにアクセスできません。これは、タイプではなくタイプであるbためです。BA

これは、オブジェクト (または子)を介してprotectedのみ の一部にアクセスできることを意味することに注意してください。A B

この場合、あなたの本当の問題を教えてください。解決のお手伝いをいたします。同型からの継承・合成はデザイン臭がする。

于 2012-09-04T20:42:19.887 に答える
0

私がテストしたすべてのコンパイラーはいくつかのことについて不平を言っていました。特に、代入ステートメントが削除されたとしても、保護されたコンストラクターは問題になります。

protected派生したタイプのインスタンスのメンバーにアクセスすることはできません。この問題は、11.4p1の例で明らかにされています。

class B {
protected:
  int i;
  static int j;
};

class D1 : public B {
};

class D2 : public B {
  void mem(B*, D1*);
};

void D2::mem(B* pb, D1* p1) {
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  // ...
}
于 2012-09-04T20:40:53.210 に答える