2011-01-28 4 views
17

私はタイトルのより良い言葉遣いを考えることができませんでしたので、少し誤解を招いていますが、私は親から継承した変数にアクセスする子供について話しているわけではありません。私はこれをコンパイルしようとした場合親の保護された変数へのアクセス

class Parent { 
    protected: 
    Parent *target; 
    int hp; 
} 

class Child : public Parent { 
    public: 
    void my_func(); 
} 

void Child::my_func() { 
    target->hp -= 50; 
} 

しかし、それは「この文脈でプライベート」である「HP」に文句を言うだろう:私が何を言っているか

はこれです。問題は、子が自身の親の変数にアクセスしようとしていないが、他のいくつかのクラス 'であり、子自体であってもなくてもよい。

オブジェクトは、同じクラスの別のオブジェクト(メモリ内の2つの別々のインスタンス)のすべての変数とメソッド(public、protected、またはprivate)にアクセスできるため、これも同様に動作すると思っていました。それはそれがアクセスしようとしているクラスのクラスから継承するので、私はそう仮定して間違っていたようです。

ヒント?

P.S.無礼なことではないですが、私はget()とset()メソッドを作成することができますが、私はよりクリーンな方法を望んでいました。

+0

ここに書かれているように(元々は誤って大文字にされた 'class'キーワード、不正な継承構文など)、多くのエラーがあります。コンパイルに失敗した最小限の例を得て、ここに正確なコードをコピーして貼り付けると便利です。 –

+1

@Tim私は、プロフィールを比較するまで、あなたが1分間自分と会話していると思った。 –

+0

ええ、私はそれについて何かしなければならない。私は思ったほどユニークではありません。 :-) –

答えて

22

メンバ関数は、実際に基本クラス、独自のクラス型のオブジェクトのサブオブジェクト(または複数の派生型である基底クラスのprotectedメンバへのアクセス権を持っています)。

あるクラスのメンバは、その基本クラスの他のインスタンスの保護されたメンバにアクセスすることができないため、実行時にそのポインタまたは参照がそのメンバ関数がアクセスしようとしているクラスの型であるオブジェクトである必要があります。アクセス制御はコンパイル時に強制されます。

など。あなたの例では

class X 
{ 
protected: 
    int z; 
}; 

class Y : X 
{ 
public: 
    int f(const Y& y) 
    { 
     return y.z; // OK 
    } 

    int g(const X& x) 
    { 
     return x.z; // Error, Y::g has no access to X::z 
    } 
}; 

あなたは(関数がメンバーとなっているクラスの型を持っている、Child)現在のオブジェクトのメンバにアクセスしているので、表現target->hpで、targetへのアクセスが合法ですtargetの型はChildへのポインタではなく、Parentへのポインタであるため、メンバhpへのアクセスは無効です。

+0

chapeau!素晴らしい例! –

+2

おそらく、私はOPで十分に明確にしていなかったかもしれませんが、私はそれを理解しています。私はget()とset()メソッドなしでこれを行う方法があるかどうかを知りたい。 – Infiltrator

+0

@ティム:私の答えはあなたの間違った前提を説明するのを助けようとしていました。悪用はありますが、必要なアクセス権限を持つようにクラス階層を修正する必要があります。 http://stackoverflow.com/questions/3364722/accessing-protected-member-of-template-parameter/3365221#3365221 –

-4

はうーん、奇妙な誰もがこれまでに言及しませんが、あなたのコードを正確にあなたかについて非常に明確ではないかもしれないので、(親の友人になる子を宣言することができ、この

Class Child : public Parent 
+1

同じ問題が公開継承で発生します。 –

+1

'Child'が' Parent'からパブリックまたはプライベートに継承するかどうかは 'Child'メソッドが' Child'の基本クラスのサブオブジェクトである 'Parent'の保護されたメンバーにアクセスしようとしているのか、そうではありません。 –

+3

-1問題とは関係ありません –

0

に変更しようここでやりたい)

class Parent { 
    friend class Child; 
    protected: 
    int hp; 
} 

class Child { 
    public: 
    void my_func(); 
    Parent *target; 
} 

これはアクセスを許可します。代わりに、あなたは国民のアクセサメソッドを書くことができます:特定のクラスの

class Parent { 
public: 
    get_hp(){return hp;} 
protected: 
    int hp; 
} 
+0

はい、私はそれを行うことができました。それは今の私のハックですが、それは継承の「下降」を破るようです。クラスを継承するすべてのクラスを友人にする必要はありません。 – Infiltrator

+0

また、私が言ったように、私はちょうどあなたの例であるset()とget()メソッドを使うことができることを知っています。私は試行しているのと同じようなやり方があるかどうかを見たいと思っています。あなたが継承を使用していなければ、あなたはできるはずです。 – Infiltrator

+0

@Tim:私がチャールズの答えに対する私のコメントで言ったように、問題は基本クラスによって表される抽象化を破りたいということです。なぜあなたはそれをしたいのか自分に尋ねる必要があります。 – sbi

4

これはとても簡単です(OPが誤解されていることを意味します。これは、人々がOPを読む時間がないためです)。

あなたは、アクセスする必要のある親の変数の友人にするだけです。

または、親クラスの友人にすることができます。

このようにして、すべての子は、親のメンバー変数にアクセスできます。これは、あなたの期待通りです。

class Child; 

class Parent { 
    protected: 
    Parent *target; 
    int hp; 
    friend void Child::my_func(); 
} 

class Child : public Parent { 
    public: 
    void my_func(); 
} 

void Child::my_func() { 
    target->hp -= 50; 
} 

これの欠点は、すべての子供がすべての親の変数にアクセスできることです。ただし、あなたのケースでは、コンパイラはParent *ターゲットがその子と同じインスタンスであることを知ることはできません。あなたがそれを目標としているとすれば、私はすべての子供があらゆる親の変数にアクセスできることがあなたの望むものであることを期待しています。

別の可能性があります。他の人には、親にアクセスするためのインタフェースを使用させ、実際の親クラスを使用するようにしてください。しかし結果は同じです。すべての子はすべての親変数にアクセスできます。

クラスをインスタンスと混同しています。 子は、同じINSTANCEの基本クラスの同じメンバー変数にアクセスできます。

+0

クラスを変数のフレンドにすることはできません。あなたは代わりに "クラス"と言うことを意味しましたか? – sbi

+0

チャールズの答えでティムに私のコメントにも注意してください。私が「保護された」と言ったことは、「友人」についてもっと真実です。クラスの抽象化を破り、友人をクラスの実装に強く結びつけます。タイトカップリングは常に悪いです。必要に応じて「友人」を使用しますが、できるだけ少なくしてください。 – sbi

+0

コピー貼り付け:はい、私はそれを行うことができ、それは今のところ私のハックですが、それは継承の "下降"を破るように思えます。クラスを継承するすべてのクラスを友人にする必要はありません。 – Infiltrator

関連する問題