10章 インタフェースクラス
http://www.geocities.jp/ky_webid/cpp/language/010.html
メンバ関数の宣言だけ書いて実際の定義はサブクラスに任せるクラスのことをインタフェースクラス(抽象クラス)といいます。
仮想関数に「=0」というのをつけると宣言だけができるそうです。なんだその書き方は・・・。ちなみにこういった関数のことを純粋仮想関数というらしいです。
とりあえず実装してみます。
#include <iostream> class IClass { public: virtual void foo() = 0; }; class CClass : public IClass { public: void foo(); }; void CClass::foo() { std::cout << "CClass::foo" << std::endl; } int main () { CClass obj; obj.foo(); return 0; }
$ main CClass::foo
面白いですね。ためしにIClassのみでインスタンス化してみたところ、コンパイルエラーになりました。
int main () { IClass obj; obj.foo(); return 0; }
$ cl /W4 /EHs main.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp main.cpp(18) : error C2259: 'IClass' : 抽象クラスをインスタンス化できません。 次のメンバが原因です: 'void IClass::foo(void)' : は抽象型です main.cpp(5) : 'IClass::foo' の宣言を確認してください。
このインタフェースクラスというのはJavaといった他の言語ではメンバ変数や定義を含めることができないそうです。
C++は関数単位で純粋仮想関数化させるだけなので他のメンバの定義が可能ということです。
僕としては有りだとは思うのですがどうなんでしょう。
仮想デストラクタ
今の時点では理由が説明できないのですが、インタフェースクラスには仮想デストラクタを宣言しておくべきです。ある状況下では、仮想デストラクタがないと処理が正しく行えません。たとえ、デストラクタで行う処理がなくとも、仮想デストラクタだけは宣言しておきましょう。そして、その定義は空にしておきます。
何故インタフェースクラスの場合は仮想デストラクタが必要なんでしょうか。後で説明があるといいですね。
実際に実装してみました。
#include <iostream> class IClass { public: virtual ~IClass() { std::cout << "IClass::~IClass" << std::endl; } virtual void foo() = 0; }; class CClass : public IClass { public: void foo(); }; void CClass::foo() { std::cout << "CClass::foo" << std::endl; } int main () { CClass obj; return 0; }
$ main IClass::~IClass
ちなみに上記のようにclass宣言の中で関数の定義をすることをinlineというそうです。この話はまた出てくるとのことなので楽しみにしてます。
で仮想デストラクタですが、よく考えればデストラクタってそれぞれのクラスで定義されるものなのでそもそもオーバーライドできないような気がするんですが、仮想関数にすることに何の意味があるんでしょうか・・・。
凄く気になりますね。後で説明あればよいのですが。