10

次の2つのクライアントのインターフェイスを分離するために仮想メソッドをプライベートにするのは良いことのようです-1。オブジェクトをインスタンス化してメソッドを呼び出すクライアント2.クラスから派生し、メソッドをオーバーライドする可能性のあるクライアント。簡単に言えば、最初のクライアントはメソッドが仮想であるかどうかを知る必要はありません。彼は基本クラスのパブリック非仮想メソッドを呼び出し、次にプライベート仮想メソッドを呼び出します。たとえば、以下のコードを参照してください。

ここで、仮想メソッドが、たとえばSaveメソッドなどの基本クラスの対応する仮想メソッドにスーパーメッセージを送信する必要がある場合、各レベルに対応するデータを保存するには、継承のチェーン内のすべての仮想メソッドを通過する必要があります。派生-スーパーメッセージングを使用せずに派生のすべてのレベルでデータの保存を保証する方法がない限り、保護された仮想メソッドを使用する以外に選択肢はありません(私が知っているものはありません)。

上記の理由が正しいかどうか知りたいのですが。

コード全体を表示するには、必ずスクロールを使用してください。

#include <iostream>
using namespace std;

class A {

    string data;    

protected:

    virtual void SaveData()= 0;

public:

    A():data("Data of A"){}

    void Save(){
        cout << data << endl;        
        SaveData();
    }
};

class B : public A {

    string data;

protected:

    virtual void SaveData() { cout << data << endl;}

public:

    B():data("Data of B") {}

};

class C : public B {

    string data;
protected:

    virtual void SaveData() {
        B::SaveData();
        cout << data << endl;
    }

public:

    C():data("Data of C") {}
};


int main(int argc, const char * argv[])
{
    C c;
    c.Save();

    return 0;
}
4

3 に答える 3

10

はい、別のクラスの SaveData を呼び出す必要がある場合は、そのクラスからアクセスできる必要がありpublicますprotected

于 2013-02-03T08:45:52.783 に答える
7

あなたはまさに正しいです:

  • NVI (非仮想インターフェイス) では、virtualメソッドがpublic
  • 基本クラスのメソッドを呼び出すには、そうでないことが必要ですprivate

したがってprotected、少なくとも C++03 では明らかな解決策です。残念ながら、派生クラスの開発者が "super" の呼び出しを忘れないように信頼する必要があります。


C++11 ではfinal、派生クラスがvirtualメソッドをオーバーライドするのを防ぐために使用できます。ただし、新しいフックを導入する必要があることを意味します。例:

class Base {
public:
    void save() {
        // do something
        this->saveImpl();
        // do something
    }
private:
    virtual void saveImpl() {}
};

class Child: public Base {
private:
     virtual void saveImpl() final {
         // do something
         this->saveImpl2();
         // do something
     }
     virtual void saveImpl2() {}
};

もちろん、毎回新しい名前を考え出さなければならないという問題があります...しかし、少なくともChild::saveImpl、その子のどれもそれをオーバーライドできないため、 が呼び出されることが保証されます。

于 2013-02-03T14:37:37.153 に答える
2

何を求めているのかわかりにくいですが、例からすると、メソッドを保護する必要はありません。実際には非公開にすることができます。機微の詳細については、次の投稿を参照してください:プライベート ピュア仮想関数のポイントとは? .

派生クラス (または外部クラス) からプライベート メンバーを呼び出さない限り、問題ありません。プライベート メンバーのオーバーライドは問題ありません。親のプライベートをオーバーライドできるというのは非常にいたずらで間違っているように聞こえますが、C++ ではこれを行うことができます。

以下は問題ありません。

#include <iostream>
using namespace std;

class A {

    string data;    

private:

    virtual void SaveData()= 0;

public:

    A():data("Data of A"){}

    void Save(){
        cout << data << endl;        
        SaveData();
    }
};

class B : public A {

    string data;

private:

    virtual void SaveData() { cout << data << endl;}

public:

    B():data("Data of B") {}

};
于 2013-02-03T08:53:03.883 に答える