LoginSignup
1
0

More than 1 year has passed since last update.

オブジェクト指向プログラミングPart5 抽象クラス MQL5

Last updated at Posted at 2021-08-25

← オブジェクト指向プログラミングPart1

← オブジェクト指向プログラミングPart4 ポリモーフィズム (前回)


純粋仮想関数と抽象クラス

 純粋仮想関数とは基底クラス内で宣言だけをして定義付けをしないメンバ関数のことです。純粋仮想関数がひとつでもあれば、そのクラスを抽象クラスと呼びます。
image.png

 抽象クラスは定義してないメンバ関数(純粋仮想関数)を含むため、プログラム内で抽象クラスを呼び出してもコンパイルエラーとなります。抽象クラスを使うためには必ず純粋仮想関数をオーバーライド(派生クラスで同じ関数を宣言、定義すること)をして、抽象クラスではなく派生クラスを呼び出して使うようにしなければいけません。
image.png

何のために抽象クラスを作るのか

  • 基底クラスを呼び出せないようにする(必ず派生クラスを使うようにする)
  • 派生クラスで必ず定義しなければいけない関数を指定する(必ずオーバーライドさせる)

 このふたつが抽象クラスを作る大きな理由です。基底クラスと派生クラスの関係はPart3で解説しましたが、実際にひとつの基底クラスに対して複数の派生クラスに枝分かれしてプログラムを書いていけば、基底クラス自体を呼び出して使うメリットがなくなっていきます。
 
 そこで基底クラスを単体で使うことはなくして、派生クラスの土台としてだけ機能させよう。というのが抽象クラスです。
image.png

実際に書いてみる

// 基底クラス (抽象クラス)
class CRen{
public: 
   virtual double Position_Sizing() = 0;  // 純粋仮想関数
};

// 派生クラス
class CPractice :public CRen{
private:
   double lot_size;

public:
   void   set_lot_size(double Lots) { lot_size = Lots; };
   double Position_Sizing(); // 純粋仮想関数をオーバーライド

};

double CPractice::Position_Sizing() 
{
   //ここにポジションサイジングのロジックを書く
   lot_size += 0.1;

   return lot_size;
}

int OnInit()
  {
   double Lots = 0.1;

   CPractice practice;     // 派生クラスオブジェクト生成


   practice.set_lot_size(Lots);

   Lots = practice.Position_Sizing();

   Print("ロット数は",Lots);


   return(INIT_SUCCEEDED);
  }

実際に動作すると↓
image.png

 ここではPosition_Sizing()という純粋仮想関数を使って抽象クラスを作ってみました。抽象クラス内ではPosition_Sizing()を定義付けしていないですが、その後オーバーライドしているため、コンパイルエラーは発生していません。

  • 純粋仮想関数をオーバーライドしていない
  • プログラム内で派生クラスではなく抽象クラスを呼び出している

このような時はコンパイルエラーとなります。

  • 派生クラスで作るつもりだった関数を書き忘れた
  • 呼び出すつもりじゃなかった基底クラスを間違えて呼んだ

こういったヒューマンエラーをコンパイルエラーで気付かせてくれるのも抽象クラスを使うメリットになります。
 

 抽象クラスは派生クラスの数が多くなってくるほどに恩恵を受けると思います。特に複数人で開発するときなどでは非常によく使われる技術なので、ぜひ覚えてみてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0