#pragma twice

KAB-studio > プログラミング > #pragma twice > 335 Version 16.08 const メンバ関数

#pragma twice 335 Version 16.08 const メンバ関数

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

 Version 16.08
const メンバ関数

今回は、 const なポインタ、参照、そして【const メンバ関数】につい
て説明します
 const メンバ関数って一応知ってるけど。これのことでしょ?

    // m_iData の getter 。
    int GetData() const;

この、関数の後ろに const って付いてるのがそうなんだよね
そう、でも実はすっごく奥の深いものなんです
そうは見えないけど……
後で、これ使いたくない! って絶対言い出すから
な! 何それ、どういうこと?
まぁそれはあとで
う……
それはともかく、まずはポインタと参照の const について
これも、クラスとして使う場合の話ね
そういうこと。でも基本的には同じだけどね。まず、 const 関係は
Version 4.12 ( No.062 ) 、 Version 4.15 ( No.065 ) 、 それに
Version 5.03 ( No.068 ) で説明しました
結構やってるね
これを踏まえて。まず、ポインタの const は二種類あります
前に付ける const と、 * の後につける const ね
そう。まず、 CData クラスは、以下のようになっているとします

// Data.h

// CDataクラス。
class CData
{
public:
    // public メンバ変数。
    int m_iData;
};

メンバ変数が public なのね
さて、次に const ポインタの使用例。まずは前に付ける const から


int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // CData クラスの変数を宣言します。
    CData cData;
    // const ポインタにアドレスを渡します。
    const CData *pcData = &cData;
    // すると、メンバ変数に値をセットできません。
    pcData->m_iData = 100;
    // コンパイルエラー:
    // error C2166: 左辺値は const オブジェクトに指定されています。

    // 取り出すことはできます。
    int i = pcData->m_iData;

    return 0;
}

このように、【const 型 *ポインタ変数名】とすると、その変数のメンバ
変数に値をセットすることができなくなります
書き換え不可になるわけね
 const ポインタと言ったら、このポインタのことを意味すると考えてく
ださい
後ろに付ける const ポインタは、 const ポインタじゃない?
うん、実際にはほとんど使わないからね……後ろに付ける const は、
ポインタ内のアドレスを書き換えることはできなくなるけれど、メンバ変数
の値は書き換えられます

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // CData クラスの変数を宣言します。
    CData cData;
    // ポインタにアドレスを渡します。
    CData *const pcData = &cData;
    // すると、アドレス値を変えることはできません。
    pcData = NULL;
    // コンパイルエラー:
    // error C2166: 左辺値は const オブジェクトに指定されています。

    // メンバ変数に値をセットすることはできます。
    pcData->m_iData = 100;

    return 0;
}

このように、アドレスそのものは変えられなくなるけど、メンバ変数は変
えられます
こっちの方がやっぱり用途少ないよね……
だね。両方同時に使うこともできるから、どっちを使うかって感じでもな
いかな
そか、困ったら両方使えばいいんだ
もうひとつ、参照について。参照の場合は、前に付ける const だけにな
ります

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // CData クラスの変数を宣言します。
    CData cData;
    // const 参照を作ります。
    const CData &rcData = cData;
    // すると、メンバ変数に値をセットできません。
    rcData.m_iData = 100;
    // コンパイルエラー:
    // error C2166: 左辺値は const オブジェクトに指定されています。

    // 取り出すことはできます。
    int i = rcData.m_iData;

    return 0;
}

 const 参照は、 const ポインタと同じく、メンバ変数に値をセットでき
ません。取り出すことはできます
 後ろに付ける const は……そか、参照はあとで参照先変数変えられない
から、元々 const ってことなんだね
そういうこと。だから、ポインタにはある、後ろに付ける const は、参照
にはないんです
ん、りょーかい
さて、ここからが本題。まず、前回説明した、ポインタを使用する
メリットについて

・変数の複製を作らずに渡す
・引数経由で値を返す
・ポリモーフィズム

このうち、【変数の複製を作らずに渡す】だけしたい場合、つまり
【引数経由で値を返す】をしたくない場合
引数を const にする!
ことになります。そのため、引数を const ポインタや const 参照にする
必要が出てきます。で
で?
先ほどの例ではメンバ変数に値をセットする場合を見てみました。ですが
実際にはメンバ変数は private なので、こういったことはしません
だよね、 SetData() とかの、 setter でセットするんだから
このメンバ関数経由で変えることができてしまったら、何の意味もないわ
けです。そこで、【 const メンバ関数】というものを使います
ここで出てくるわけね
たとえば、 読み出し専用の getter メソッドに使用します

// Data.h

// CDataクラス。
class CData
{
private:
    // private メンバ変数。
    int m_iData;

public:
    // m_iData の getter 。
    int GetData() const;

    // m_iData の setter 。
    void SetData( int p_iData );
};

// Data.cpp
#include <Windows.h>
#include <stdio.h>

#include "Data.h"

// m_iData の getter 。
int CData::GetData() const
{
    return m_iData;
}

// m_iData の setter 。
void CData::SetData( int p_iData )
{
    m_iData = p_iData;
}

このように、メンバ関数の () の後ろに const を付けると、その
メンバ関数が const メンバ関数になります
なるとどうなるの?
まず、 const メンバ関数からメンバ変数の値を変えることができなくな
ります

// m_iData の getter 。
int CData::GetData() const
{
    m_iData = 100;
    // コンパイルエラー:
    // error C2166: 左辺値は const オブジェクトに指定されています。

    return m_iData;
}

お、ホントだ
これが、 const メンバ関数の一番基本的な機能。でも、ここからが複雑
なんです……ふふふ
ふふふ!?

/*
    Preview Next Story!
*/
なにがふふふなのー?
……ここからは本当に大変だよ?
何驚かせるようなこと言って
 const メンバ関数の恐ろしさは……
恐ろしさは……?(ごくっ)
というわけで次回
< Version 16.09 const メンバ関数が呼べる・呼ばれる関数 >
につづく!
……今から引き返してもいいんだよ?
いいの? じゃあ引き返す
あ待ってごめん
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。