C++私有和受保护的虚拟方法

MMR*_*MMR 7 c++

似乎最好将虚方法设置为私有,以便分离用于跟随两个客户端的接口 - 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;
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 9

是的,如果你需要调用另一个类的SaveData,它需要可以从该类访问 - 所以public或者protected.


Mat*_* M. 5

你是完全正确的:

  • NVI(非虚拟接口)要求virtual方法不是public
  • 调用基类方法要求不要 private

因此protected是显而易见的解决方案,至少在C++ 03中是这样.不幸的是,这意味着你必须相信派生类开发人员不要忘记称为"超级".


在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() {}
};
Run Code Online (Sandbox Code Playgroud)

当然,每次都不得不提出一个新名字的麻烦......但至少你保证Child::saveImpl会被调用,因为它的孩子都不能覆盖它.