I was reading about the NVI Idiom and most examples follow this form
#include <iostream>
class Base {
public:
    virtual ~Base() = default;
    void do_something() {
        do_something_impl();
    }
private:
    virtual void do_something_impl() = 0;
};
class Derived : public Base {
private:
    void do_something_impl() override {
        std::cout << "Hello, world!\n";
    }
};
void foo(Base& b) {
    b.do_something();
}
int main() {
    Derived d;
    foo(d);
}
I have always had it in my head that "A private member of a class is only accessible to the members and friends of that class" (from cppreference), When do_something_impl is implemented in Derived, is the access specifier not taken into consideration? Or is Derived a member of Base? Does implementing a virtual function not count as "accessing"? I'm not sure which part of the language allows this.
From this [emphasis added]:
If some member function
vfis declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same
- name
- parameter type list (but not the return type)
- cv-qualifiers
- ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides
Base::vf(whether or not the word override is used in its declaration).
Base::vfdoes not need to be accessible or visible to be overridden. (Base::vfcan be declared private, or Base can be inherited using private inheritance. Any members with the same name in a base class of Derived which inherits Base do not matter for override determination, even if they would hideBase::vfduring name lookup.)
class B {
    virtual void do_f(); // private member
 public:
    void f() { do_f(); } // public interface
};
struct D : public B {
    void do_f() override; // overrides B::do_f
};
int main()
{
    D d;
    B* bp = &d;
    bp->f(); // internally calls D::do_f();
}
Overriding the virtual function does not count as accessing. However if you need to call the base implementation, that would be impossible to do from Derived.
class Base {
public:
    virtual ~Base() = default;
    void do_something() {
        do_something_impl();
    }
private:
    virtual void do_something_impl() { /*Default implementation*/ }
};
class Derived : public Base {
private:
    void do_something_impl() override {
        //Base::do_something_impl() is not accessible from here:
        //Base::do_something_impl();
        std::cout << "Hello, world!\n";
    }
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With