0

このようなことをするのは合理的ですか?

注:これは最小限の作業例です

class A {
    public:
        int getX() { return x; }
    protected:
        int x;
        virtual void setX(int newX) = 0;
};

// Children can modify X
class Can_Modify_X : public A {
     protected:
         void setX(int newX) { x = newX; }
     private:
         using A::x;
};

// Children can't modify X
class Can_Not_Modify_X : public A {
     private:
         void setX(int newX) { }
         using A::x;
};

Liskov Principleに違反するため、関数を単純に非表示にすることはできないことは承知していますが、private継承を行ってすべてのパブリックメソッドを再度指定するのは本当に冗長に思えます。

2 つのクラスには共通の親が必要であり (それが直接の 1 つであっても)、x直接変更できてはなりません。

usingボーナス:誰かがこの場合の正確な動作を定義する場所を教えてもらえますか? 私はそれをグーグルで試しましたが、ほとんど成功しませんでした。

4

3 に答える 3

1

リスコフの原則に違反するため、関数を単純に非表示にすることはできないことを認識しています。

まったく同じ概念がデータメンバーにも当てはまります。

Can_Modify_Xまたはのインスタンスへのポインタ(または参照)があるとしますCan_Not_Modify_Xxこの参照を介してデータメンバーにアクセスしたり、データメンバーを変更したりすることはできません。この派生クラスポインタをクラスへのポインタにアップキャストすると、A突然データメンバーを変更できますxx非公開にすることで、リスコフの置換原則に違反していることになります。xデータメンバー、メンバー関数、または型定義のいずれであるかは関係ありません。あなたは純粋で単純なリスコフの置換に違反しています。

派生クラスは、親クラスによって提供される機能を隠してはなりません。

于 2012-12-04T23:48:36.717 に答える
0

次のコードは何をすると思いますか?

A * a = new Can_Not_Modify_X();
a->setX(10);
于 2012-12-04T22:41:56.777 に答える
0

これは主観的な質問なので、私の回答はそれに応じて主観的になります。

合理的ではないと断言します。protected属性を使用すると、子クラスが誤って状態を変更したり、不変条件に違反したりすることが非常に簡単になるため、それらを完全に回避することをお勧めします。次に、親クラスはx、パブリックまたは保護されたインターフェイスを介して維持されます (できれば、単なるミューテーターではなく、意味のあるメソッドのセットを介して)。

インターフェイスがすでにアクセスを適切に制御しているため、子のアクセシビリティを変更する必要はありません。

それだけでなく、メンバーまたはメソッドのアクセシビリティを変更すると、最小の驚きの原則に違反し、将来のメンテナーに問題を引き起こす可能性が高くなります。

于 2012-12-04T23:06:46.687 に答える