第12章 第3のアクセス指定子

 前回の CTextFile クラスにメンバを追加していくと、致命的な欠点があることに気が付きます。しかし、この欠点は簡単に解消できます。今回はそんなお話です。


 では、今回の要点です。


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


 今回も CTextFile をパワーアップさせていきましょう。

 前回文字列を書き込む関数がうまく言ったので、今回は1行読み出す関数を作りたいと思います。1行読み出す関数には fgets という関数があるので、これを使いたいと思います。

// TextFile.h
#ifndef __TEXTFILE_H__INCLUDED__
#define __TEXTFILE_H__INCLUDED__

#include <stdio.h>
#include <string.h>
#include "File.h"

const int TF_OVERFLOW = EOF - 1;  // オーバーフロー

class CTextFile : public CFile
{
public:
    int WriteString(const char* pszString);  // 文字列を書き込む
    int ReadLine(char* buffer, int nSize);   // 1行読み出す関数
};

#endif
// TextFile.cpp
#include <stdio.h>
#include "TextFile.h"

// 1行読み出す関数
// 改行コードは切り捨てられます
// 戻り値は文字列の長さになります
// バッファに入りきらないとき(オーバーフロー)は TF_OVERFLOW を返します
int CTextFile::ReadLine(char* buffer, size_t nSize)
{
    if(IsValid() == false)
        return EOF;
    if(fgets(buffer, nSize, m_pfile) == NULL)
        return EOF;

    size_t nLength = strlen(buffer);

    // 最後に改行のない場合は、オーバーフローか、改行のない最後の行です
    // 改行のない最後の行がたまたまバッファの長さ−1の長さの時もオーバーフローと判定します
    if(buffer[nLength - 1] != '\n')
        return (nLength == nSize - 1) ? TF_OVERFLOW : nLength;

    nLength -= 1;
    buffer[nLength] = 0;
    return nLength;
}
エラーコード
TextFile.cpp(13) : error C2248: 'm_pfile' : private メンバにアクセスできません。

 おや? エラーが出てきました。「private メンバにアクセスできません」? どうやら、private メンバは派生先にも公開されないようです。

 これは困ったどころの問題ではありません。m_pfile は確かに外部に公開したくないメンバ変数です。だからといって派生クラスでも使えないというのはどうしたものでしょうか。

 実は、こういうときのために第3のアクセス指定子があります。それが protected: です。protected:(守られた)と書くと、以降のメンバは外部には公開されませんが、派生先には公開されます。

 つまり、CFile の部分をこうしておけばいいのです。

class CFile
{
    // メンバ変数
protected:
    FILE* m_pfile;  // ファイル

private:
    bool  m_bCopy;  // コピーコンストラクタで作られたかどうか

    // 以降は省略
};

 これで m_pfile は派生クラスでも使えるようになりました。これで ReadLine 関数も無事コンパイルすることができますね。

 m_bCopy は特に派生クラスで使える必要はないので、private のままにしておきました。このように、派生クラスで使わせないためにあえて private にすることも重要です

 public, private, そして protected の3つのアクセス指定子を使って、上手にメンバ変数を保護してあげましょう。


 今回はこれ以上することがないので、これらのクラスを使ったプログラムでも作って終わりにします。まだ CTextFile でもバイナリモードで開かれるのですが、気にしないことにしましょう。

プログラム実行結果
// TestFile.cpp
#include <iostream.h>
#include "File.h"
#include "TextFile.h"

int main()
{
    CFile     bin;
    CTextFile txt;
    char      buffer[128];
    int       nRead;

    if(txt.Open("Test.txt", "w") == false)
        return 0;
    txt.WriteString("色は匂へど散りぬるを");
    txt.Close();

    if(bin.Open("Test.txt", "r") == false)
        return 0;
    nRead = bin.Read(buffer, sizeof buffer - 1);
    buffer[nRead] = 0;
    cout << buffer << endl;

    return 0;
}
色は匂へど散りぬるを

 先ず、CTextFile の方で WriteString で文字列を書き込みます。

 そして、次に CFile の方でその文字列を読み込みます。で、ヌルターミネータを付けてから文字列を表示しています。動作に問題はありませんね。


 では、今回の要点です。


 次回は、CTextFile だとテキストモードで開かれるようにしたいと思います。それでは。


第11章 子孫 | 第13章 関数のすげ替え

Last update was done on 2000.9.7

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