C++:多態性と関数の多重定義

ここではC++による多態性と関数の多重定義の例を紹介します。
多態性オブジェクト指向プログラミングにおける素晴らしい技法の一つです。多態性を利用すると同じ関数名でオブジェクトに応じたオブジェクトの操作が可能になります。一方、多態性が利用できないとオブジェクトごとに関数名を変えてオブジェクトを操作しなければなりません。
以前、オブジェクト指向プログラミングの講習を受けたことがあるのですが、その時の講師は多態性を次のように説明していました。 一つの命令(関数名)でオブジェクトごとに異なる動作をさせることができる。例えば、鳥オブジェクトに“動け”と命令すれば鳥は空を飛ぶ、魚オブジェクトに“動け”と命令すれば魚は海を泳ぐ、と言ったぐあいです。
尚、C++の場合は、関数の多重定義を使って同様のことが実現できます。(下記の overloading.cpp を参照)
また、多人数でソフトウェアを開発する際、関数の多重定義が利用できる言語では、各プログラマは関数名の衝突を気にせずに関数名を付けることができます。

関数 calculate の多態性(polymorphism)の例
calculate の引数が、Operand1 のオブジェクトの場合には加算、Operand2 のオブジェクトの場合には乗算を実行します。

polymorphism.cpp

#include <iostream>

class Operand {
public:
  virtual auto calculate() -> void;
};

class Operand1 : public Operand {
  double x, y;
public:
  Operand1(double x = 0, double y = 0);
  auto calculate() -> void;
};

Operand1::Operand1(double x, double y) : x{x}, y{y} {}

auto Operand1::calculate() -> void {
  std::cout << x + y << std::endl;
}

class Operand2 : public Operand {
  double x, y;
public:
  Operand2(double x = 0, double y = 0);
  auto calculate() -> void;
};

Operand2::Operand2(double x, double y) : x{x}, y{y} {}

auto Operand2::calculate() -> void {
  std::cout << x * y << std::endl;
}

auto calculate(Operand* operand) -> void {
  operand->calculate();
}

auto main() -> int {
  auto operand1 = new Operand1(1, 1);
  auto operand2 = new Operand2(2, 2);
  calculate(operand1); // -> 1 + 1 = 2
  calculate(operand2); // -> 2 * 2 = 4
}
 

 

関数 calculate の多重定義(overloading)の例
上記と同様のことが、関数の多重定義を使っても実現できます。はっきり言って、C++の場合はこちらの方が簡単です^^

overloading.cpp

#include <iostream>

class Operand1 {
  double x, y;
public:
  Operand1(double x = 0, double y = 0);
  auto calculate() -> void;
};

Operand1::Operand1(double x, double y) : x{x}, y{y} {}

auto Operand1::calculate() -> void {
  std::cout << x + y << std::endl;
}

class Operand2 {
  double x, y;
public:
  Operand2(double x = 0, double y = 0);
  auto calculate() -> void;
};

Operand2::Operand2(double x, double y) : x{x}, y{y} {}

auto Operand2::calculate() -> void {
  std::cout << x * y << std::endl;
}

auto calculate(Operand1* operand1) -> void {
  operand1->calculate();
}

auto calculate(Operand2* operand2) -> void {
  operand2->calculate();
}

auto main() -> int {
  auto operand1 = new Operand1(1, 1);
  auto operand2 = new Operand2(2, 2);
  calculate(operand1); // -> 1 + 1 = 2
  calculate(operand2); // -> 2 * 2 = 4
}
 

 


g++ -std=c++17 -O3 *.cpp -o main.exe