antenn-a
company profile

MFC航海日記 18日目(自前で作った無継承クラスの罠?)

今回に限らず、一つのツールを作成しようと思ったとき、自前でクラスを作らないという事はまず無いと言える。(かな?) もちろん、作らなくても開発は可能であるが自前のクラスを作成した方がより開発が楽に進むものである。

例えば、今回開発するツールの場合バックアップする設定を一つのパターンとし、複数個のバックアップパターンの内、必要なものをユーザが選択し、バックアップするようなツールに仕上げたいと思っている。 そういった場合、そのバックアップパターンを一括で管理・保存をするクラスがあれば便利である事は言うまでもないだろう。

ここでは、そのバックアップパターン一括管理クラスをここで「BACKPU_PATTERN」と呼ぶ事にする。 このクラスは別にWindowを表示するわけでもないし、Windowsコントロールに依存するわけでもないから、無継承クラスという事になる。 しかし、クラスウィザードで普通にクラスを作成しようとすると必ずなにかMFCに絡んだクラスを継承しなければならない。 もちろん、継承したって使わなければ同じなのだが「それも嫌だな」という方の為に今回は執筆してみた。

何を隠そう筆者はVC(Visual C++)を初めて使ったときに、自前で作ったクラスをプロジェクトに加えて意味の分からないエラーに苦しんだ経験がある。 このページを読んでいる方の中にも居ると思うが、本当に意味が分からないのである。 エラーメッセージは「・・・行目に予期せぬEOFが検出されました」というもので、正直言って「???」な心境だったのを覚えている。

未だにこのエラーの根本的な理由は分からないのだが、このエラーが出たときの対処方法は見つけた!(オイオイ)

それでは、実際に無継承クラスをプロジェクトに加える方法を順を追って解説してみたい。
・・・・と、ここまで読んだ方の中で「何こいつ?あほちゃう?そんなのも知らんの?」という方・・・飛ばして下さい。。。。

必要なファイルは、基本的には「*.h」「*.cpp」の2つである。 知らない方は居ないと思うが念のために書いておくと、前者を「ヘッダ部」といい後者を「実装部」と呼んだりもする。 尚、ここから先は「BACKUP_PATTERN」クラスをプロジェクトに加えるという仮定の元で話を進めていく


prev

まず、ヘッダ部に下記のコードを「必ず」書く。
#ifndef   BACKUP_PATTERN_H   //
ここは通常すべて大文字でファイル名の
「.」を_に変えて書くことが多い

#define   BACKUP_PATTERN_H

#endif    BACKUP_PATTERN_H

この3行はいわゆる「おまじない」に近いものだが、一応概略を書いておく。 あるファイル「A」が「B」というファイルをインクルードしていたとする。 その時、「B」が「A」をインクルードしていたらどうなるだろう? 当たり前だが、無限ループが発生する。

だが、両方のファイルが両方に依存するケースは少なくない。 そういった場合に、上記の「おまじない」を書く必要がある。 最初の行を無理矢理日本語に訳すと、「もしBACKUP_PATTERN_Hというのが定義されてなければ次へ進みなさい」となる。 次の行は「BACKUP_PATTERN_Hを定義します。」となる。 つまり、以前にここを通っていれば2回目は一行目の所ではじかれるわけである。 もっと言えば、無限ループを回避できるのである。

この2行を書いたならば、この2行が有効になっている領域を指定しなければならない。 その最終行を示すのが最後の文章である。

もっと詳しい内容を知りたい方はC言語の参考書(かなり詳しいやつ)をご覧ください。


prev

筆者の場合、最初の2行と最後の行の間に本文を書いている。 下記のような感じである。
#ifndef    BACKUP_PATTERN_H   //
ここは通常すべて大文字でファイル名の
「.」を_に変えて書くことが多い

#define    BACKUP_PATTERN_H

#include   string.h

#include   dir.h

class    BACKUP_PATTERN

{

public:

BACKUP_PATTERN();

//その他のメンバー関数

};

#endif    BACKUP_PATTERN_H
後は通常通りに記述していけばよい。

次に、実装部(cpp)だが、ここで落とし穴が待っていた・・・・
最初、筆者は下記のようなコードを書いた。


#include    "BackupPattern.h"

BACKUP_PATTERN::BACKUP_PATTERN()

{

}

//その他のメンバー関数

分かった方はすぐに気が付いたと思う。 今まで使ってきた「Borland C++」では、このように記述して問題無くコンパイル・実行できたはずなのに、なぜか「Visual C++」ではできない。 隠すような事では無いので、いきなり答えを書かせていただくが下記のコードが正解である。

#include   "stdafx.h"

#include   "BackupPattern.h"

//ここに必要なファイルをインクルード

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

BACKUP_PATTERN::BACKUP_PATTERN()

{

}

//その他のメンバー関数

prev

なぜ?どうして?という方、調べて下さい。 筆者には未だに理解できません。 分かっている事は
  • stdafx.hのインクルード分は「必ず」先頭行に書く事
  • その実装部ファイルに関連するヘッダファイルをインクルードする事
  • その他の「おまじない」を書く事
の3つである。

このようにすれば、問題無くコンパイル・実行ができる。
なぜかな?>MS


antenn-a

prev next


antenn-a