今回は継承を使ったクラスを関数に渡してみたいと思います。「何だ、それだけか」と思われるかもしれませんが、それだけじゃないんです、これが。
では、今回の要点です。
では、いってみましょう。
今回は、ファイルを開く部分を別の関数(メンバ関数ではありません)にしたいと思います。ファイル名を入力し、そのファイルを開くという関数です。
この際渡す引数は、やはり CFile もしくは CTextFile のオブジェクトです。ということで、早速やってみたいと思います。
#include <iostream.h> #include "File.h" #include "TextFile.h" bool Open(CFile& rfile, const char* pszFlags) { char buffer[512]; cout << "ファイル名を指定して下さい > " >> flush; cin >> buffer; return rfile.Open(buffer, pszFlags); } bool Open(CTextFile& rfile, const char* pszFlags) { char buffer[512]; cout << "ファイル名を指定して下さい > " >> flush; cin >> buffer; return rfile.Open(buffer, pszFlags); } |
型が違うからこうしたのですが...何というか、不経済ですね。
そういえば第11章で、「派生クラスは基底クラスのメンバを全て持っている」と言いました。なら、派生クラスのオブジェクトを基底クラスへの参照に渡しても、動作に問題はなさそうです。基底クラスのメンバは全て持っているわけだから、データが多いことはあっても、足りないことはないはずです。
そして、Open 関数は CFile のものを使っているので、その呼び出しに問題はないはずです。
というわけで、CTextFile への参照をとる関数は消して、CFile への参照をとる関数だけを残しましょう。
プログラム |
---|
// TestFile.cpp #include <iostream.h> #include "MainDefs.h" #include "File.h" #include "TextFile.h" bool Open(CFile& rfile, const char* pszFlags) { char buffer[512]; cout << "ファイル名を指定して下さい > " << flush; cin >> buffer; return rfile.Open(buffer, pszFlags); } void Write(CTextFile& rtxt) { char buffer[512]; cout << "何を書き込みますか > " << flush; cin >> buffer; rtxt.WriteString(buffer); } void Load(CFile& rbin) { char buffer[512]; int nRead; nRead = rbin.Read(buffer, numof(buffer)); buffer[nRead] = 0; cout << buffer << endl; } int main() { CFile bin; CTextFile txt; if(Open(txt, "w") == false) return 0; Write(txt); txt.Close(); if(Open(bin, "r") == false) return 0; Load(bin); bin.Close(); return 0; } |
実行結果例 |
ファイル名を指定して下さい > Test.txt CFile::Open CTextFile::ModifyFlags 何を書き込みますか > ペペロンチーノ ファイル名を指定して下さい > Test.txt CFile::Open CFile::ModifyFlags ペペロンチーノ |
おお、きちんと動きました。CTextFile の ModifyFlags が呼ばれています。
このように、派生クラスのオブジェクトを基底クラスへの参照、ポインタに対して渡すことは可能です。このことをアップキャストと言います。
しかし、ちょっと待って下さい。そういえば仮想関数を使っていましたね。これって何か影響あるんでしょうか?
では、virtual を消してもう一度やってみましょう。
実行結果例 |
---|
ファイル名を指定して下さい > Test.txt CFile::Open CFile::ModifyFlags 何を書き込みますか > ペスカトーレ ファイル名を指定して下さい > Test.txt CFile::Open CFile::ModifyFlags ペスカトーレ |
今度は CFile の ModifyFlags が呼ばれてしまいました。
これは前回と同じ状況ですね。CFile の参照から呼ばれたから CFile の ModifyFlags が呼ばれたのです。そして、それを回避し、オブジェクトの本当の型に対する ModifyFlags を呼ぶために仮想関数を使うわけです。
最後にもう一度仮想関数についてまとめます。
普通は、呼び出すときに使った型に対応する関数が呼ばれます。しかし、仮想関数にしていれば、そのオブジェクトの本当の型に対応する関数が呼ばれるのです。
では、今回の要点です。
それでは、また次回まで。
Last update was done on 2000.8.21
この講座の著作権はロベールが保有しています