C++の仮想関数とポリモーフィズム
仮想関数とは
仮想関数(virtual function)とは、C++において基底クラスで定義され、 派生クラスでオーバーライド可能な関数のことです。 これにより、基底クラスのポインタや参照を介して、派生クラスのメソッドを呼び出せるようになります。
仮想関数の基本的な使い方
例えば、動物の鳴き声を表現するクラスを考えてみます。
#include <iostream>
using namespace std;
class Animal {
public:
virtual void makeSound() { // 仮想関数
cout << "Animal makes a sound." << endl;
}
};
class Dog : public Animal {
public:
void makeSound() override { // オーバーライド
cout << "Woof!" << endl;
}
};
class Cat : public Animal {
public:
void makeSound() override { // オーバーライド
cout << "Meow!" << endl;
}
};
int main() {
Animal* a = new Dog();
a->makeSound(); // "Woof!"と出力される
a = new Cat();
a->makeSound(); // "Meow!"と出力される
delete a;
return 0;
}
ここで、makeSound()
をvirtual
として宣言することで、
ポリモーフィズムが機能し、Animal*
型のポインタ経由で派生クラスの関数が適切に呼び出されます。
ポリモーフィズムとは
ポリモーフィズム(polymorphism)は、オブジェクト指向プログラミングにおける重要な概念の一つで、 あるインターフェースを通じて異なる型のオブジェクトを扱うことを可能にします。
C++では、主に仮想関数を利用することで動的ポリモーフィズムを実現します。 これにより、同じ基底クラスを持つ異なるオブジェクトが、異なる動作を実装できるようになります。
ポリモーフィズムの具体例
次のコードでは、異なる図形の面積を計算するためのポリモーフィズムを示します。
#include <iostream>
using namespace std;
class Shape {
public:
virtual double getArea() const = 0; // 純粋仮想関数
};
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double getArea() const override {
return width * height;
}
};
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double getArea() const override {
return 3.14 * radius * radius;
}
};
int main() {
Shape* shape1 = new Rectangle(10, 5);
Shape* shape2 = new Circle(7);
cout << "Rectangle Area: " << shape1->getArea() << endl;
cout << "Circle Area: " << shape2->getArea() << endl;
delete shape1;
delete shape2;
return 0;
}
この例では、Shape
クラスが純粋仮想関数を定義しており、
それをRectangle
とCircle
が実装しています。
仮想デストラクタの必要性
仮想関数を持つクラスを正しく継承して使うためには、デストラクタも仮想関数にする必要があります。
class Base {
public:
virtual ~Base() { cout << "Base destructor" << endl; }
};
これにより、派生クラスのデストラクタが正しく呼ばれるようになります。
仮想テーブル(vtable)とは
仮想関数を実装するために、C++のコンパイラは仮想テーブル(vtable)を使用します。 vtableは、仮想関数へのポインタを持つテーブルであり、実際の関数呼び出し時に適切な関数を特定する役割を果たします。
仮想関数の応用
仮想関数は、以下のような応用分野で広く利用されています。
- デザインパターン(Factoryパターン、Strategyパターンなど)
- プラグインシステム
- ゲーム開発(異なるキャラクターの動作を統一的に扱う)
仮想関数を適切に使うことで、柔軟で拡張性のあるコードを書くことができます。