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
vf
is 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::vf
does not need to be accessible or visible to be overridden. (Base::vf
can 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::vf
during 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