C++ の仮想関数
この記事では、C++ の virtual
関数について説明します。 仮想関数は、派生宣言によってオーバーロードまたはオーバーライドされる特別なメンバー関数ですが、基本クラスで定義および宣言されています。
C++ の仮想関数
キーワード virtual
は、基本クラスの関数宣言の前に付加されます。 これにより、コンパイラは、関数の動的リンケージとも呼ばれる遅延バインディングを実行します。
実行時の遅延バインディングまたはダイナミック リンケージ コンパイラは、オブジェクト タイプを決定し、関数呼び出しをバインドします。 簡単に言えば、実行時に関数呼び出しが解決されるバインディングの一種です。
ランタイム ポリモーフィズムは、これらの関数を使用して実現されます。 そのため、C++ の関数が仮想化されるたびに、コンパイラは実行時に、基本クラス ポインターが指すオブジェクトに基づいて呼び出す必要がある関数を決定します。
コード例:
#include <bits/stdc++.h>
using namespace std;
class demo {
public:
virtual void fun() { cout << "Inside the base class\n"; }
void check() { cout << "Base class function\n"; }
};
class derived : public demo {
public:
void fun() { cout << "Inside the derived class\n"; }
void check() { cout << "Derived class fuction\n"; }
};
int main() {
demo *ptr;
derived d;
ptr = &d;
ptr->fun();
ptr->check();
}
出力:
Inside the derived class
Base class function
上記のコードでは、ptr->fun()
は仮想関数であるため、実行時にバインドされますが、ptr->check()
は非仮想関数であるため、コンパイル時にバインドされます。 ここでは、派生クラスのオブジェクトを指す基本クラス ポインターを使用して、ランタイム ポリモーフィズムが実現されています。
C++ における仮想関数の規則
仮想関数を操作するときは、次の規則に留意する必要があります。
-
仮想コンストラクターを持つことはできませんが、仮想デストラクタを持つことはできます。 仮想デストラクタを使用すると、派生クラス オブジェクトが正しい順序で破棄されます。 まず、基本クラス オブジェクトが破棄され、次に派生クラスが破棄されます。
コード例:
#include <bits/stdc++.h> using namespace std; class demo { public: demo() { cout << "Constructing base class\n"; } virtual ~demo() { cout << "Destroying base class\n"; } }; class derived : public demo { public: derived() { cout << "Constructing derived class\n"; } virtual ~derived() { cout << "Destroying the derived class\n"; } }; int main() { demo *ptr; derived *derivedPtr = new derived(); ptr = derivedPtr; delete ptr; }
出力: 適切な構築と破棄の順序に従っていることがわかります。
Constructing base class Constructing derived class Destroying the derived class Destroying base class
- ランタイム ポリモーフィズムを実現する場合は、仮想関数で基本クラス ポインターまたは基本クラス参照のみを使用する必要があります。
- 仮想関数は決して静的ではありません。
- 仮想関数プロトタイプは、基本クラスと派生クラスで同じままにする必要があります。
- 仮想関数は、別のクラスの
friend
関数にすることもできます。
C++ の純粋仮想関数について
これらの関数は、元の仮想関数のわずかなバリエーションです。 純粋仮想関数は、何もしない仮想関数です。
構文:
virtual void fun() = 0
純粋仮想関数は、抽象クラスを作成するために使用されます。 これらはオブジェクトを作成できないクラスであり、これらから派生したクラスは純粋仮想関数をオーバーライドする必要があります。 それ以外の場合、それらも抽象クラスとして扱われます。
コード例:
#include <bits/stdc++.h>
using namespace std;
class demo {
public:
virtual void fun() = 0;
};
class derived : public demo {
public:
void fun() // overriding the function
{
cout << "Inside the derived class";
}
};
int main() {
demo *ptr;
// demo d; This will give compile error as base class demo is abstract class
derived d;
ptr = &d;
ptr->fun();
}
出力:
Inside the derived class