2012-04-09 5 views
1

私は、Messageクラスのオブジェクトを持っています。私の知る限り見ることができるように、MessageUpdateは、IS-MessageWrite:C++:派生クラスのメソッドアクセスを制限する

class MessageWrite 
{ 
    protected: 
    void setVersion(int version_) {...} 
    void setReceiveTime(int tmReceive_) {...} 

    Message _msg; 
}; 


class MessageUpdate:public MessageWrite 
{ 
    //ONLY setVersionShould be accessible here, NOT setReceiveTime 
}; 

これを達成するのを助けることができますメソッドのアクセスレベルと継承レベルの組み合わせがありますか?

私はMessageUpdateを単純に基底クラスにすることができますが、メッセージクラスを拡張したい場合はダイヤモンドパターンになります。検討してください:

class MessageUpdate {...}; 
class MessageWrite: public MessageUpdate {...}; 


//Now, while extending: 
class AdminMessageUpdate:public MessageUpdate {...}; 
class AdminMessageWrite: public AdminMessageUpdate, public MessageWrite //DIAMOND Pattern!! 

私は継承の理解のギャップはどこですか?そして、多重継承なしでこのロジックを達成するための全く別の方法がありますか(後者のコードのように)?

+0

ダイヤモンドパターンは限りOKですが、[仮想継承] (http://en.wikipedia.org/wiki/Virtual_inheritance)。 – dasblinkenlight

+0

仮想基底クラスを使用して、継承ツリーに「MessageWrite」の複数のコピーを作成しないようにする例については、http://stackoverflow.com/a/21607/13140を参照してください。ですから、MessageWriteだけがsetReceiveTime()を呼び出せるようにしたいのですか? –

+0

dasblinkenlightに感謝しますが、私は複数の継承のランタイムコストも節約できるので、@Alsの方法を好むでしょう – vid

答えて

1

MessageWriteのすべてのメンバーがprotectedなので、あなただけ作ることができるMessageUpdate内部setReceiveTime()privateMessageUpdateから継承するクラスがそれにアクセスすることはできませんので。しかし、私はまだあなたのデザインにいくつかの問題があります:

あなたのデザインがダイヤモンドをどのように回避するのですか? (MessageWriteのすべてではないが、それに適用されることを指定することで)

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessageWrite:public MessageWrite {...}; 
class AdminMessageUpdate: public AdminMessageWrite, public MessageUpdate //DIAMOND Pattern!! 

は、なぜあなたはMessageUpdateは、IS-MessageWriteあなたは後でそれがないと言うと思います:それは均等につながると思いませんか?このコードは有効であってはならない場合は、次の

MessageWrite& m = MessageUpdate(); 
m.setReceiveTime(); // Should this be valid? 

そしてMessageUpdateは、IS-NOT-MessageWrite。コードが有効な場合はsetReceiveTime()へのアクセスを避ける理由はありませんMessageUpdate

そして、あなたはおそらく、ダイヤモンドを避けるために、基本クラスAdminMessageを作成し、そこから直接継承したほうが良いでしょう:あなたが恐れていないよう

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessage {...}; 
class AdminMessageWrite: public MessageWrite, public AdminMessage {...}; 
class AdminMessageUpdate: public MessageUpdate, public AdminMessage {...}; // No diamond 
0

protected:継承されたメンバーはアクセスできます。

private:継承されたメンバーはアクセスできません。基底クラスMessageWriteprivateアクセス指定子で

private: 
void setReceiveTime(int tmReceive_); 

protected: 
    void setVersion(int version_) {...} 
    private: 
    void setReceiveTime(int tmReceive_) {...} 
2

だけでメソッドを宣言。

鉱山のこの答えは良い読まれるべきである:MessageUpdateは、

What are access specifiers? Should I inherit with private, protected or public?

+0

でsetReceiveTime()を呼び出すことはできません。これを自動的に行う方法はありませんか?すべてのメソッド宣言を書き直さなければなりませんか? – vid

+0

@vid:これは手動で行う必要があります。また、クラスメンバのアクセス指定子は、メソッド宣言のクラス定義で指定されています。通常、クラスメソッドはヘッダーファイルで*宣言され、* cppファイルで*定義されています。 –

1

場合MessageWrite、その定義により、その保護や公共のメンバーのすべてへのアクセスを持っています。

あなたはMessageUpdateで公開したくないあなたが公に/ MessageWriteにprotectedly-公開するメンバーがあるのであれば、その後Liskov Substitution Principleにより、MessageUpdateMessageWriteすることはできません。

+0

+1の原則 – vid