5

次のコードを検討してください。

class Base
{
public:
    virtual void Foo() {}
};

class Derived : public Base
{
private:
    void Foo() {}
};

void func()
{
    Base* a = new Derived;
    a->Foo(); //fine, calls Derived::Foo()

    Derived* b = new Derived;
//  b->Foo(); //error
    static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}

この問題について、私は 2 つの異なる考え方を聞いたことがあります。

1) ユーザーは static_cast を使用してアクセスできるため、基本クラスと同じようにアクセシビリティを維持します。

2) 関数をできるだけ非公開にする。ユーザーが a->Foo() を必要とし、b->Foo() を必要としない場合、Derived::Foo は非公開にする必要があります。必要に応じていつでも公開できます。

どちらか一方を好む理由はありますか?

4

3 に答える 3

6

サブタイプのメンバーへのアクセスを制限すると、リスコフ置換の原則( SOLIDの L ) が破られます。私は一般的にそれに対してアドバイスします。

更新:コードがコンパイルおよび実行され、期待される出力が生成されるため、「機能する」可能性がありますが、メンバーを非表示にしている場合、おそらくサブタイプが元のタイプよりも一般的ではなくなりますこれが原則を破るものです。代わりに、API のユーザーにとって興味深いものだけを残してサブタイプ インターフェイスをクリーンアップすることを意図している場合は、先に進んで実行してください。

于 2012-04-27T06:43:58.207 に答える
3

元の質問への回答ではありませんが、クラスの設計について話している場合...

Alexandrescu と Sutter が 39番目のルールで推奨しているように、パブリックな非仮想関数とプライベート/保護された仮想関数を使用することをお勧めします。

class Base {
public:
    void Foo(); // fixed API function

private:
    virtual void FooImpl(); // implementation details
};

class Derived {
private:
    virtual void FooImpl(); // special implementation
};
于 2012-04-27T08:24:27.323 に答える
1

virtualこれは、派生クラス オブジェクトを使用して関数にアクセスするかどうかにかかわらず、設計によって異なります。
そうでない場合は、それらをprivateまたはprotectedにする方が常に良いです。

アクセス指定子に基づくコード実行の違いはありませんが、コードはきれいになります。クラスの関数
へのアクセスを制限したら、virtualその読者は、classこれが派生クラスのオブジェクトまたはポインターで呼び出されないことを確認できます。

于 2012-04-27T06:42:57.797 に答える