読者です 読者をやめる 読者になる 読者になる

GoF本のためのC++入門 (その4)

C++ 連載

前回に引き続き、GoFデザインパターン本(オブジェクト指向における再利用のためのデザインパターン)に載っているサンプルコードを読むためにC++を勉強してるよ。

今日は抽象クラスを使ってみる。抽象クラスってのは、実態がない形式的な関数を含むクラスのことだ。その関数のことをC++では純粋仮想関数って言うらしい。いわゆる抽象メソッドだね。

今回は絶対値を求めるメンバ関数を含むクラスを作る。まず始めに抽象クラスとして定義する。

#include <iostream>
#include <cmath>

using namespace std;

// 抽象クラス
class VirtualElement {
public:
    // 絶対値関数
    virtual double absolute() = 0;
};

= 0ってつけると純粋仮想関数になる。ただしこのクラスは中身がないのでインスタンス化できない。なのでこいつを継承した実数クラスを作ってみる。

// 実数クラス
class R : public VirtualElement {
public:
    R(double x);
    // このabsoluteメソッドがないとコンパイルエラーになる
    double absolute();

private:
    double value;
};

R::R(double x)
{
    value = x;
}

double R::absolute()
{
    // 実数の絶対値を返す
    return value >= 0 ? value : -value;
}

絶対値の計算を実装した(そうじゃないとコンパイルエラーになる)。計算方法は例のアレ(マイナスの符号をとっぱらうやつ)ね。

で、一つだけだと何なので、もう一つ、複素数クラスを作ってみる。

// 複素数クラス
class Complex : public VirtualElement {
public:
    Complex(double x, double y);
    double absolute();

private:
    double re;  // 実部
    double im;  // 虚部
};

Complex::Complex(double x, double y)
{
    re = x;
    im = y;
}

double Complex::absolute()
{
    // 複素数の絶対値を返す
    return sqrt(re * re + im * im);
}

こっちも絶対値の計算を実装した。複素数の絶対値は例のアレ(2乗してルート)ね。

というわけで、このクラスをさっそくつかってみる。

int main()
{
    VirtualElement* e[3];

    //e[0] = new VirtualElement(); //=> これはコンパイルエラーになる
    e[0] = new R(8);
    e[1] = new R(-9);
    e[2] = new Complex(3, 4); // 3 + 4i のこと

    for (int i = 0; i <= 2; i++) {
        // VirtualElement* 型なのでabsolute関数が呼び出せる
        cout << "|e[" << i << "]| = " << e[i]->absolute() << endl;
    }

    delete e[0];
    delete e[1];
    delete e[2];

    return 0;
}

出力はこんな感じ。

e[0] = 8
e[1] = 9
e[2] = 5
うん、ちゃんと計算できてる。というわけでまとめると、virtual メンバ関数の宣言 = 0;って出てきたら純粋仮想関数なので、どこか別のところでオーバーライドしてるはずだよ。 < 前へ | 次へ > この連載の一覧