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

C++/CLI で純粋仮想関数を持っている抽象クラスを使います。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. 次のように宣言されている関数を純粋仮想関数と言い、純粋仮想関数を持っているクラスを抽象クラスと呼びます。
    Draw() は Zukei クラスのメンバー関数ですが、Zukei を継承したクラスでオーバーライドされることが前提で、このままでは実行出来ません。
    //純粋仮想関数を持っている抽象クラス
    class  Zukei
    {
      public:
        virtual void  Draw() = 0;   //純粋仮想関数
    };
    
  2. Zukei クラスを継承して、図形の代わりに○を表示するプログラムを作成してみましょう。
    このように Draw() 関数をオーバーライドすることで実行出来るようになります。
    継承の説明は class を継承します を参照して下さい。
    /*★ 純粋仮想関数と抽象クラス    前田 稔 ★*/
    #include <stdio.h>
    
    //純粋仮想関数を持っている抽象クラス
    class  Zukei
    {
      public:
        virtual void  Draw() = 0;   //純粋仮想関数
    };
    
    class  Maru : public Zukei
    {
      public:
        void    Draw()  {  printf("○");  }
    };
    
    int main()
    {
        Maru    *p;
    
        p = new Maru;
        p->Draw();
        return 0;
    }
    
  3. 次は Zukei クラスを継承して「○, △, □」を表示するプログラムを作成してみましょう。
    Zukei *p[10]; は基本クラスのポインタ配列ですが、ここに派生クラスのポインタを格納することが出来ます。
    最初の描画ループで何が表示されるかを考えて下さい。
    二回目の描画ループで何が表示されるかを考えて下さい。
    /*★ 純粋仮想関数と抽象クラス    前田 稔 ★*/
    #include <stdio.h>
    
    //純粋仮想関数を持っている抽象クラス
    class  Zukei
    {
      public:
        virtual void  Draw() = 0;   //純粋仮想関数
    };
    
    class  Maru : public Zukei
    {
      public:
        void    Draw()  {  printf("○");  }
    };
    
    class  Sankaku : public Zukei
    {
      public:
        void    Draw()  {  printf("△");  }
    };
    
    class  Shikaku : public Zukei
    {
      public:
        void    Draw()  {  printf("□");  }
    };
    
    int main()
    {
        Zukei   *p[10];
    
        p[0] = new Maru;
        p[1] = new Sankaku;
        p[2] = new Sankaku;
        p[3] = new Shikaku;
        p[4] = new Shikaku;
        p[5] = new Shikaku;
        for(int i=0; i<6; i++)  p[i]->Draw();
        printf("\n\n");
        for(int i=3; i<6; i++)  p[i] = p[i+1];
        for(int i=0; i<5; i++)  p[i]->Draw();
        return 0;
    }
    

【注意】

基本クラスのポインタに派生クラスのポインタを格納するときは注意が必要です。
次のプログラムを実行してみて下さい。
child Class の Destructor が実行されません。
#include <iostream>

class super
{ public:
    super(){};
    ~super(){ std::cout << "super end" << std::endl; };
    virtual void hoge() = 0;
};

class child : public super
{ public:
    child(){};
    ~child(){ std::cout << "child end" << std::endl; };
    void hoge(){ std::cout << "hoge" << std::endl; };
};

void  main()
{
    super *test = new child();
    test->hoge();
    delete test;
    test = NULL;
}

child Class の Destructor を実行するには super Class の Destructor に virtual の指定が必要なようです。
    virtual ~super()
    {
        std::cout << "super end" << std::endl;
    };
この結果からも継承される可能性がある super Class の Destructor には virtual を付けるのが無難なようです。

超初心者のプログラム入門(C/C++)