C++ private and protected virtual method

后端 未结 3 1363

It seems that it is good to make the virtual methods private in order to separate the interfaces for following two clients - 1. clients that instantiate an object and call the

相关标签:
3条回答
  • 2021-02-08 22:41

    Yes, if you need to call the SaveData of another class, it needs to be accessible from that class - so public or protected.

    0 讨论(0)
  • 2021-02-08 22:42

    It's difficult to tell what you're asking, but from the example, you do not need to make the method protected. It actually can be private. For details about the subtleties see this post: What is the point of a private pure virtual function?.

    So long as you're not calling the private member from derived class (or outside classes), you're ok. Overriding of private members is ok. It does sound quite naughty and wrong that you can override your parent's privates, but in c++ you're allowed to do this.

    The following should be ok:

    #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") {}
    
    };
    
    0 讨论(0)
  • 2021-02-08 22:56

    You are exactly right:

    • NVI (Non-Virtual Interface) requires that virtual methods not be public
    • Calling the base class method requires that it not private

    therefore protected is the obvious solution, at least in C++03. Unfortunately it means you have to trust the derived class developer not to forget to call "super".


    In C++11, you can use final to prevent a derived class from overriding a virtual method; it means though that you are forced to introduce a new hook, example:

    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() {}
    };
    

    Of course, there is the trouble of having to come up with a new name each and every time... but at least you are guaranteed that Child::saveImpl will be called because none of its children can override it.

    0 讨论(0)
提交回复
热议问题