C++の仮想関数とポリモーフィズム

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クラスが純粋仮想関数を定義しており、 それをRectangleCircleが実装しています。

仮想デストラクタの必要性

仮想関数を持つクラスを正しく継承して使うためには、デストラクタも仮想関数にする必要があります。


class Base {
public:
    virtual ~Base() { cout << "Base destructor" << endl; }
};

これにより、派生クラスのデストラクタが正しく呼ばれるようになります。

仮想テーブル(vtable)とは

仮想関数を実装するために、C++のコンパイラは仮想テーブル(vtable)を使用します。 vtableは、仮想関数へのポインタを持つテーブルであり、実際の関数呼び出し時に適切な関数を特定する役割を果たします。

仮想関数の応用

仮想関数は、以下のような応用分野で広く利用されています。

  • デザインパターン(Factoryパターン、Strategyパターンなど)
  • プラグインシステム
  • ゲーム開発(異なるキャラクターの動作を統一的に扱う)

仮想関数を適切に使うことで、柔軟で拡張性のあるコードを書くことができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です