この質問は、仮想関数のオーバーライドと非仮想関数の非表示の違いは何ですか?に少し関連しています。、しかし、私は技術的な詳細についてではなく、非仮想関数と仮想関数の使用について尋ねています。
ここで少し背景を説明します。基本クラス A と 2 つの派生クラス 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() を実装しないままにしておくと、派生クラス B および C での bar() への呼び出しはすべて A::bar() に解決されます。非仮想関数である xorp() は、派生クラスから b.xorp() または bA::xorp() として呼び出すこともできます。
たとえば、B に xorp() を実装すると、A::xorp() が効果的に非表示になり、b.xorp() の呼び出しは実際には bB::xorp() の呼び出しになります。
上記の例を使用して、私の質問に行きます。派生クラスの実装に必要なヘルパー関数があるとします。
ヘルパー関数を非仮想メンバー関数 (xorp() など) にすることと、ヘルパー関数を派生クラスがオーバーライドしない仮想関数 (bar()) にすることの間に違いはありますか?
クラス オブジェクト レイアウトと VTABLE に関するこのプレゼンテーション ( https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx、スライド 28 ~ 35) を読んでも、実際には違いを見つけることができませんでした。 -仮想関数とオーバーライドされていない仮想関数が同じ場所 (基本クラスの関数) を指している
これら2つのアプローチが異なる結果をもたらす例、または私が見つけていない警告がある場合、誰かが私に例を挙げてもらえますか?