#pragma twice

KAB-studio > プログラミング > #pragma twice > 217 Version 11.17 コンストラクタとデストラクタを作る!

#pragma twice 217 Version 11.17 コンストラクタとデストラクタを作る!

前のページへ 表紙・目次へ 次のページへ

 Version 11.17
コンストラクタとデストラクタを作る!

まず、前回の補足から。前回作った CHasMemberFunction って、いつも見
てるクラスとちょっと違ってなかった?
あ、そういえばメンバ関数って、クラスの中にないよね、フツー
そう。このクラスをいつものように、メンバ関数を外に出して書くとこう
なります

// メンバ関数を持つクラス。
class CHasMemberFunction
{
private:
    int m_iData;

public:
    int GetData() const;
    void SetData( int p_i );
};

// ここからがメンバ関数の定義。
int CHasMemberFunction::GetData() const
{
    return m_iData;
}

void CHasMemberFunction::SetData( int p_i )
{
    m_iData = p_i;
}

普通は、 CHasMemberFunction 本体はヘッダーファイルの方に置いて、
メンバ関数そのものはソースファイルの方に置きます
ダイアログクラスとかそうだよね
でも、前回みたいに書く事もできるってことで
どっちの方がいいの?
微妙。前回の方は、クラスの中に全部入ってるからそれさえ見ればいいっ
ていうメリットがあります
うん、ヘッダーファイルだけでいいんだもんね
でも、今回みたいに書くと、クラスの方にはメンバ関数一覧が載ってて一
覧になる、っていうメリットがあります
でも、それって ClassView 見ればいいんじゃない?
そうだね。実は、前回の方法はとっても複雑な問題があって、初心者には
おすすめしません
ええっ!? 何その複雑な問題って
簡単に言えば、ソースファイルは〈見られてない〉けど、ヘッダーファイ
ルは〈見られてる〉ってこと
???
この件は2章くらい後になってから説明するから
ぶー、なんかかなり先
ま、それだけ難しいってことで。だから、自分でちゃんとしたクラスを作
る時には、今回の方法、つまりソースとヘッダーに分けるようにしてね
はーい
でも、説明は前回の方法で書くから

そっちの方がクラス全体をいっぺんに載せられるしね。では、今回のテー

コンストラクタとデストラクタを作るの?
そう。実は簡単

// コンストラクタを持つクラス。
class CHasConstructor
{
public:
    // コンストラクタ。
    CHasConstructor()
    {
        TRACE( "CHasConstructor::CHasConstructor()\n" );
    }

    // デストラクタ。
    ~CHasConstructor()
    {
        TRACE( "CHasConstructor::~CHasConstructor()\n" );
    }
};

そう言えば言ってたね、コンストラクタはクラス名と同じで、デストラク
タは ~ が付くって
そう、 ~ だからね。 ^ じゃないから気を付けて
 ~ とか ^ ってなんてゆーの?
 ~ は【チルダ】が正式名称。でも【にょろ】っていうこともあるかな。 ^
は【ハット】が正式名称だと思う
ハットって帽子?
そう。あ、あと、コンストラクタとデストラクタ、両方とも戻り値がない
って事に注意してね
ホントだ。なんで?
だって、受け取れないでしょ。使用例はこんな感じ

void Use_CHasConstructor()
{
    CHasConstructor cHasConstructor;
}

変なことすれば受け取れそうな気もするけど、こういう使い方だと戻り値
は無理っぽいね
ブレークポイント置いてステップインとかしてみると、どういうふうに関
数が呼ばれるのかわかると思うよ
ほい。うん、変数が作られた時にコンストラクタが呼ばれて、この関数か
ら出るときに変数が消えるからデストラクタが呼ばれてる
で、今のは本当にテスト用だから、今度はもう少し実用的なものを見てみ
ましょう

class CHasConstructorAlloc
{
private:
    int *m_piData;

public:
    // コンストラクタ。
    CHasConstructorAlloc()
    {
        m_piData = new int;
        *m_piData = 0;
    }

    // デストラクタ。
    ~CHasConstructorAlloc()
    {
        delete m_piData;
    }

    // データを返します。
    int GetData() const
    {
        return *m_piData;
    }
};

えーっと、 int のポインタをメンバ変数として持ってて、コンストラク
タで new してデストラクタで delete 、あー Version 11.12 ( No.212 ) 
で言ってたのだね
そういうこと。こういうふうに、コンストラクタとデストラクタで対に処
理させればいいわけ。一応、使い方は

void Use_CHasConstructorAlloc()
{
    CHasConstructorAlloc cHasConstructorAlloc;
    TRACE
        ( "%d\n"
        , cHasConstructorAlloc.GetData()
        );
}

こういう感じ
 GetData() は前回のと同じ感じね
そう。これは重要なことなんだけど、こういう時に

    // こういうメンバ関数は作っちゃダメ!
    int *GetDataPoionter()
    {
        return m_piData;
    }

ってメンバ関数をこのクラスに作っちゃダメだから
中のポインタを直接返してるんだね。でもなんでこれがいけないの?
こういう使い方ができるから

void Use_CHasConstructorAlloc_Bad()
{
    CHasConstructorAlloc cHasConstructorAlloc;
    int *pi = cHasConstructorAlloc.GetDataPoionter();
    free( pi );
}

ポインタを受け取って……げ!!  free() で解放してる!!
まぁこれはかなり極端な例だけど、こういうことができるってこと
このメンバ関数がなければできない?
うん。 m_piData は private だからアクセスできないでしょ
そのための private ?
そういうこと。たとえばね、 m_piData を public にして、外で new し
たり delete したりってすることもできるわけ
でもそれって意味ないじゃん
そう、ちゃんと new と delete でしたいから、 private にして、こうい
うふうにクラスの中だけで処理してるわけ
その方が確実だもんね
でも、場合によっては new と delete じゃいけないっていうときもある
かもしれない
場合?
 API 使って特殊なことしなきゃいけないときとか
あー、そういう機能があるって言ってたね
そういう場合でも、このクラスを使う限り、それは無理なわけ
修正しちゃえばいいんじゃない?
そう、結局そうなるわけだね。修正しない限り、クラスの動作は変えられ
ない。クラスが正しい処理をしてくれれば、それは修正しない限り必ず正し
く処理される。でも間違った処理をしていれば
修正しない限り直らない
そう。クラスには、こういう〈閉じている〉っていう性質があるんです
閉じてる、周りから邪魔されない、だから結果は確実
そういうこと
って、これってなんか重要な事?
実はすごく重要なことなんだけど、それは先の先の話って事で
先の先……

/*
    Preview Next Story!
*/
なんか先ばっか!
プログラミングって、全部が継ながってたりするから
全体像が見えてこないとわかんない?
そう。かといって全体像だけ見ても
わからない、と
というわけで次回
< Version 11.18 コンストラクタって複雑! >
につづく!
というわけでコンストラクタについてもっと細かく見てみましょう
それが全体像の理解に継ながると?
きっと
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。