第20章 デストラクタ(仮)

 今回は、動的確保とアップキャストを併せて使ってみます。アップキャストを忘れたという人は第15章を見返してみて下さい。


 では、今回の要点です。


 では、いってみましょう。


 さて、アップキャストというのがありました。これは、派生元のクラスへのポインタや参照に、派生先のクラスのオブジェクトを渡せるというものでした。

 これを利用すれば派生元の関数を使う処理はまとめてしまうことが出来るのでしたね。

 ということで、今回は CFile へのポインタに動的に確保したオブジェクトを渡してみます。アップキャストですね。

 では、次のプログラムを見て下さい。

プログラム1
// TextFile.h
class CTextFile : public CFile
{
public:
    ~CTextFile();  // デストラクタ
};
プログラム2
// TextFile.cpp
// デフォルトコンストラクタ
CTextFile::CTextFile()
{
    cout << "CTextFile::CTextFile 1" << endl;
}

// 構築と同時にファイルを開く
CTextFile::CTextFile(const char* pszPath, const char* pszFlags)
{
    cout << "CTextFile::CTextFile 2" << endl;
    Open(pszPath, pszFlags);
}

// コピーコンストラクタ
CTextFile::CTextFile(const CTextFile& rother) : CFile(rother)
{
    cout << "CTextFile::CTextFile 3" << endl;
}

// デストラクタ
CTextFile::~CTextFile()
{
    cout << "CTextFile::~CTextFile" << endl;
}
プログラム3
// TestFile.cpp
#include <iostream.h>
#include "File.h"
#include "BinFile.h"
#include "TextFile.h"

// 読み出し
void Read(CFile* pfile)
{
    if(pfile->Open("Test.txt", "r") == false)
        return;

    char buffer[512];

    pfile->Read(buffer, sizeof buffer);
    cout << buffer << endl;
    pfile->Close();
}

// 書き込み
void Write(CFile* pfile)
{
    if(pfile->Open("Test.txt", "w") == false)
        return;

    char buffer[] = "食すな危険";

    pfile->Write(buffer, sizeof buffer);
    pfile->Close();
}

int main()
{
    CFile* pfile;

    pfile = new CBinaryFile;
    if(pfile == NULL)
        return 0;
    Write(pfile);
    delete pfile;

    pfile = new CTextFile;
    if(pfile == NULL)
        return 0;
    Read(pfile);
    delete pfile;

    return 0;
}
実行結果
CBinaryFile::CBinaryFile 1
CFile::Open
CBinaryFile::ModifyFlags
CTextFile::CTextFile 1
CFile::Open
CTextFile::ModifyFlags
食すな危険

 一見きちんとしているようですが...何と、デストラクタで表示されるはずの文字列が表示されていません。どうやら、CFile へのポインタを使っていたので、CFile のデストラクタが呼ばれてしまったようです。

 耳にタコができるような言い回しです。こういうときはどうすればいいのか、もうわかりますね?

 そうです。デストラクタは仮想関数にしないといけないわけです。

プログラム
// File.h
class CFile
{
public:
    virtual ~CFile();  // デストラクタ
};
実行結果
CBinaryFile::CBinaryFile 1
CFile::Open
CBinaryFile::ModifyFlags
CBinaryFile::~CBinaryFile
CTextFile::CTextFile 1
CFile::Open
CTextFile::ModifyFlags
食すな危険
CTextFile::~CTextFile

 オブジェクトがこのように扱われる可能性は常にあるわけであって、継承するときは必ずデストラクタを仮想関数にしなければなりません

 継承しないときも仮想関数にして実害はないので、デストラクタは仮想関数にするという癖をつけておいた方がいいかもしれませんね。


 短いですが、これで終わりです。では、今回の要点です。


 第20章で継承が終わらなかったです。残念。というわけで、次回も継承に関することをやりたいと思います。それでは。


第19章 動的オブジェクト | 第21章 メンバの呼び分け

Last update was done on 2000.10.13

この講座の著作権はロベールが保有しています