導入
「鳴く動物」を作りたいが、Animal 自体を実体化する意味はない――中身は子に必ず実装させたい。そんなときは「純粋仮想関数」を使い、そのクラスを「抽象クラス(インターフェース)」にします。
説明
virtual void speak() = 0; のように = 0 を付けると「純粋仮想関数」になります。中身を持たず、子に実装を強制します。純粋仮想関数を1つでも持つクラスは「抽象クラス」となり、それ自体はインスタンス化できません。
flowchart TB S["Shape(抽象クラス)<br/>virtual double area() = 0;<br/>※実体は作れない"] S --> C["Circle : area() を実装"] S --> R["Rectangle : area() を実装"]
#include <iostream>
using namespace std;
class Shape {
public:
virtual double area() const = 0; // 純粋仮想関数(中身なし)
virtual ~Shape() {} // 仮想デストラクタ(次レッスン)
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return 3.14159 * r * r; }
};
class Rectangle : public Shape {
double w, h;
public:
Rectangle(double w, double h) : w(w), h(h) {}
double area() const override { return w * h; }
};
int main() {
// Shape s; // ← エラー(抽象クラスは実体化できない)
Shape* shapes[] = { new Circle(2), new Rectangle(3, 4) };
for (Shape* s : shapes) {
cout << s->area() << endl; // 12.5664 / 12
}
for (Shape* s : shapes) delete s;
return 0;
}
このように、Shape は「面積を返せる」という約束(インターフェース)だけを決め、実際の計算は各図形に任せます。新しい図形を足したいときは、Shape を継承して area() を実装するだけで済みます。
まとめ
= 0 を付けた純粋仮想関数を持つクラスは抽象クラスになり、子に実装を強制します。これで「共通の約束(インターフェース)」を定義でき、拡張に強い設計ができます。C++ に interface キーワードはなく、これがその役割を果たします。