10

Is it possible to getting rid of error C2243?

class B {};
class D : protected B {};

D d;
B *p = &d;   // conversion from 'D *' to 'B &' exists, but is inaccessible

I had this error in my app and at the end I've managed to compile it by making an explicit conversion:

D d;
B *p = (B*)&d;

I can't understand why by making class D inherited protected from B makes the implicit conversion inaccessible.

I tried to avoid explicit conversion by creating a operator B() in class D in order to make the conversion accessible:

class B {};
class D : protected B 
{
 public:
 operator B() {return *this;}
};

But there is no way.

Any other solution to avoid explicit conversion?

4

6 に答える 6

18

変換を許可する場合は、パブリック継承を使用する必要があります。

保護された継承またはプライベート継承を使用して、派生型が基本クラスから継承するという事実は、外部からは見えないはずの詳細であると宣言しています。そのため、エラーが発生します。

非公開の継承は、メソッドをオーバーライドする可能性が追加された構成の形式として のみ見なす必要があります。

于 2009-09-24T13:51:05.273 に答える
8

protectedandprivate継承は関係ではないためis-a、合成のための構文糖衣にすぎません。クラスはこのように正確に書き直すことができますが、コンパイラーに定義bさせ、明示的に参照する代わりに b メンバーを直接使用するという利便性が失われます。

class D
{
  protected:
  B b;
};

あなたの質問の2番目のポイントについて:

operator B() {return *this;}

この行は と に関係していBますD。D* と B* は、それらへのポインターですが、B と D とはまったく異なります。ポインターをキャストするには、ポインターを再解釈できます。

B *p = reinterpret_cast<B*>(&d); // TOTALLY WRONG, although it compiles :)

上記の行を実行しないでください。あなたが達成しようとしていることについて、より多くの情報を提供していただけると思います。

于 2009-09-24T13:49:21.343 に答える
2

DとDの子のうち、それらが親子であることを誰も知らないため、明示的に行う必要があります。

それが保護された継承の意味です。あなたの家族(子供)だけがあなたが継承することを知っています。そして、それを使用することができます。たとえば、子メソッドでは、暗黙の変換が合法です。

あなたがあなたの子供から暗黙の回心を持ちたいならば、あなたはそれを誰もが知っているように公開する必要があります。

于 2009-09-24T13:51:06.177 に答える
2

ここでの問題は、保護された属性が提供する情報隠蔽を回避しようとしているということです。D のインスタンスに B としてアクセスしたい場合、パブリックではなくプロテクトとして継承したのはなぜですか? 保護された継承を使用する際に言っていることは、D のインスタンスとその子孫のみが B コンポーネントを認識できるようにしたいということです。自分のやりたいことをもう一度見つめ直す必要があります。

使用している古い C スタイルのキャストには、新しい C++ キャストの微妙な点がないため、コンパイルされるコードが得られますが、問題は実際には継承にあります。

于 2009-09-24T14:07:46.173 に答える
0

クラスDで演算子B()を公開してみましたか?あなたが示したコードでは、保護されているとマークされていて、まだアクセスできません。ただし、可能であれば、変換演算子は一般的に避けたいと思います。

それでも、保護されたBを継承するということは、B * p =&dを実行しないようにすることを意味します。Bが実際にDの先頭にある保護されたメンバー変数であると想像してください。その場合、Dbにアクセスできないのと同じように、それをキャストしない限り、B*としてdにアクセスすることはできません。

したがって、Bを公に継承するか、キャストを使用します。保護されたBを継承すると、基本的に「私をBとして使用しないでください」と表示されるため、Bを公に継承することにします。これは、とにかく実行しようとしていることです。

于 2009-09-24T13:54:24.203 に答える
0

外部の誰も彼らが親子であることを知らないため、D の派生クラスでのみこのアクションを実行できます。これは例です (Visual Studio 2013 でのテスト):

class BASE{};

class BASE1 :protected BASE{};

class BASE2 :protected BASE1
{
public:
    void func(BASE &a, BASE1 &b){a = b;}
};

void main()
{
    BASE a;
    BASE1 b;
    BASE2 c;

    c.func(a, b);;
    system("pause");
 }
于 2014-11-24T10:34:40.970 に答える