Этот вопрос немного связан с В чем различия между переопределением виртуальных функций и сокрытием не виртуальных функций? , но я не спрашиваю о технических деталях, а скорее об использовании не виртуальных и виртуальные функции.
Вот небольшой фон. Допустим, у меня есть базовый класс A и два производных класса B и C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in A\n"; };
virtual void bar() { std::cout << "bar() called from A\n"; };
void xorp() { std::cout << "xorp() called from A\n"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in B\n"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in C\n"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
Это выводит, как и ожидалось, следующее:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
Если я оставлю виртуальную функцию bar () не реализованной в производных классах, любой вызов bar () в производных классах B и C будет преобразован в A :: bar (). xorp (), которая не является виртуальной функцией, также может вызываться из производных классов как b.xorp () или b.A :: xorp ().
Если бы я реализовал, например, xorp () в B, он бы эффективно скрывал A :: xorp (), а вызов b.xorp () фактически был бы вызовом bB :: xorp () .
Что подводит меня к моему вопросу, используя приведенный выше пример. Допустим, у меня есть вспомогательная функция, которая необходима производным классам для их реализации.
Есть ли разница между тем, что вспомогательная функция является не виртуальной функцией-членом (например, xorp ()), и вспомогательной функцией, являющейся виртуальной функцией, которую производные классы не переопределяют (bar ()) ?
Прочитав эту презентацию о расположении объектов класса и VTABLE (https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx, слайды 28-35), я не смог заметить разницу, поскольку как виртуальные, так и не переопределенные виртуальные функции указывают на одно и то же место ( т.е. функция в базовом классе)
Может ли кто-нибудь дать мне пример, где эти два подхода дали бы разные результаты, или если есть предупреждение, которое я не заметил?