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

実装がわからないため、すべての関数の実装を基本クラスで提供できない場合があります。このようなクラスは と呼ばれます 抽象クラス たとえば、Shape を基本クラスとします。 Shape で関数draw()の実装を提供することはできませんが、すべての派生クラスにはdraw()の実装が必要であることがわかっています。同様に、Animal クラスには move() の実装がありません (すべての動物が移動すると仮定) が、すべての動物が移動方法を知っている必要があります。抽象クラスのオブジェクトを作成することはできません。

純粋仮想関数 C++ の (または抽象関数) は、実装できる仮想関数です。ただし、その関数を派生クラスでオーバーライドする必要があります。そうしないと、派生クラスも抽象クラスになってしまいます。純粋仮想関数は、宣言内で 0 を割り当てることによって宣言されます。

純粋な仮想関数の例

C++




// An abstract class> class> Test {> > // Data members of class> public> :> > // Pure Virtual Function> > virtual> void> show() = 0;> > /* Other members */> };>

完全な例

純粋な仮想関数は、抽象クラスから派生したクラスによって実装されます。

C++




// C++ Program to illustrate the abstract class and virtual> // functions> #include> using> namespace> std;> class> Base {> > // private member variable> > int> x;> public> :> > // pure virtual function> > virtual> void> fun() = 0;> > // getter function to access x> > int> getX() {> return> x; }> };> // This class inherits from Base and implements fun()> class> Derived :> public> Base {> > // private member variable> > int> y;> public> :> > // implementation of the pure virtual function> > void> fun() { cout < <> 'fun() called'> ; }> };> int> main(> void> )> {> > // creating an object of Derived class> > Derived d;> > // calling the fun() function of Derived class> > d.fun();> > return> 0;> }>

出力

fun() called 

いくつかの興味深い事実

1. 少なくとも 1 つの純粋仮想関数を持つクラスは抽象クラスです。

以下の C++ コードでは、Test には純粋な仮想関数 show() があるため、Test は抽象クラスです。

C++




// C++ program to illustrate the abstract class with pure> // virtual functions> #include> using> namespace> std;> class> Test {> > // private member variable> > int> x;> public> :> > // pure virtual function> > virtual> void> show() = 0;> > // getter function to access x> > int> getX() {> return> x; }> };> int> main(> void> )> {> > // Error: Cannot instantiate an abstract class> > Test t;> > return> 0;> }>

出力

Compiler Error: cannot declare variable 't' to be of abstract type 'Test' because the following virtual functions are pure within 'Test': note: virtual void Test::show() 

2. 抽象クラス型のポインタと参照を持つことができます。

たとえば、次のプログラムは正常に動作します。

C++




// C++ program that demonstrate that> // we can have pointers and references> // of abstract class type.> #include> using> namespace> std;> class> Base {> public> :> > // pure virtual function> > virtual> void> show() = 0;> };> class> Derived :> public> Base {> public> :> > // implementation of the pure virtual function> > void> show() { cout < <> 'In Derived '> ; }> };> int> main(> void> )> {> > // creating a pointer of type> > // Base pointing to an object> > // of type Derived> > Base* bp => new> Derived();> > // calling the show() function using the> > // pointer> > bp->show();>>

出力

In Derived 

3. 派生クラスの純粋仮想関数をオーバーライドしない場合、派生クラスも抽象クラスになります。

次の例は同じことを示しています。

C++




// C++ program to demonstrate that if we do not override> // the pure virtual function in the derived class, then> // the derived class also becomes an abstract class> #include> using> namespace> std;> class> Base {> public> :> > // pure virtual function> > virtual> void> show() = 0;> };> class> Derived :> public> Base {> };> int> main(> void> )> {> > // creating an object of Derived class> > Derived d;> > return> 0;> }>

出力

Compiler Error: cannot declare variable 'd' to be of abstract type 'Derived' because the following virtual functions are pure within 'Derived': virtual void Base::show() 

4. 抽象クラスにはコンストラクターを含めることができます。

たとえば、次のプログラムはコンパイルされ、正常に実行されます。

C++




// C++ program to demonstrate that> // an abstract class can have constructors.> #include> using> namespace> std;> // An abstract class with constructor> class> Base {> protected> :> > // protected member variable> > int> x;> public> :> > // pure virtual function> > virtual> void> fun() = 0;> > // constructor of Base class> > Base(> int> i)> > {> > x = i;> > cout < <> 'Constructor of base called '> ;> > }> };> class> Derived :> public> Base {> > // private member variable> > int> y;> public> :> > // calling the constructor of Base class> > Derived(> int> i,> int> j)> > : Base(i)> > {> > y = j;> > }> > // implementation of pure virtual function> > void> fun()> > {> > cout < <> 'x = '> < < x < <> ', y = '> < < y < <> ' '> ;> > }> };> int> main(> void> )> {> > // creating an object of Derived class> > Derived d(4, 5);> > // calling the fun() function of Derived class> > d.fun();> > // creating an object of Derived class using> > // a pointer of the Base class> > Base* ptr => new> Derived(6, 7);> > // calling the fun() function using the> > // pointer> > ptr->楽しい();>>

出力

Constructor of base called x = 4, y = 5 Constructor of base called x = 6, y = 7 

5. C++ の抽象クラスは、struct キーワードを使用して定義することもできます。

struct shapeClass { virtual void Draw()=0; } 

Javaとの比較

Java では、抽象キーワードを使用してクラスを抽象化できます。同様に、抽象キーワードを使用すると、関数を純粋仮想または抽象にすることができます。見る Javaの抽象クラス 詳細については。

インターフェイスと抽象クラス

インターフェイスにはメソッドの実装はなく、メソッド宣言のコレクションと考えることができます。 C++ では、すべてのメソッドを純粋仮想にすることでインターフェイスをシミュレートできます。 Java では、インターフェイス用の別のキーワードがあります。

インターフェイスは C++ のヘッダー ファイルと考えることができます。ヘッダー ファイルではインターフェイスを実装するクラスの本体のみを提供するのと同様です。同様に、Java in Interface ではクラスの本体のみを提供し、それを実装するクラスに実際のコードを記述します。