#pragma twice

KAB-studio > プログラミング > #pragma twice > 346 Version 16.19 型変換演算子のオーバーロード

#pragma twice 346 Version 16.19 型変換演算子のオーバーロード

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

 Version 16.19
型変換演算子のオーバーロード

「今回は最後のオーバーロード、型変換演算子のオーバーロードについて説
明します」
『一度やってるんだよね』
「 Version 11.20 ( No.220 ) で説明したけど、今回はその復習。まずは例
から」

// Data.h

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

    // 型変換演算子のオーバーロード。
    operator int();
};

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

#include "Data.h"

// 型変換演算子のオーバーロード。
CData::operator int()
{
    return m_iData;
}

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

#include "Data.h"

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    CData cData;
    cData.m_iData = 100;

    // 型変換演算子のオーバーロードを使用します。
    int i = cData;

    char pch[256];
    sprintf( pch, "%d\n", i );
    OutputDebugString( pch );
    // 100

    return 0;
}

「まず、【型変換演算子】っていうのは、具体的に言うとキャストのこと」
『キャストって、 (int)i とかのキャスト?』
「それもそうだし、そうはっきりと書かないキャストも含みます」
『はっきり書かないキャスト?』
「たとえば int 型の変数に char 型の値を代入したときとか、そういう、
型は違うんだけど変換して渡せる、そういうものもキャストに含むんです」
『そういうキャストも全部ひっくるめて、型変換演算子、って言うと?』
「そういうこと。演算子、っていうのには抵抗あるかもしれないけどね」
『うん、抵抗ある』
「変数の値に対して何らかの処理をして結果を返す、っていう点では演算子
なんだよね。演算子の性質としては、 ! 演算子とかが近いかも」
『 TRUE と FALSE を入れ替える?』
「そう。あれと同じ、値を変換して返す、そういう意味での演算子」
『うーん、なんかちょっと納得いかないけど……』
「まぁ名前の問題だから、それほど深く考えなくてもいいかも。今回の例で
は、以下の箇所が、型変換演算子を使用している箇所になります」

    // 型変換演算子のオーバーロードを使用します。
    int i = cData;

「 CData クラスの変数から int 型の変数に代入しようとしているので、
コンパイラは CData から int へ型変換しようとします」
『でも普通できないよね』
「そう、できません。そこで、型変換演算子をオーバーロードします。以下
のメンバ関数が、 int 型の型変換演算子のオーバーロードです」

// 型変換演算子のオーバーロード。
CData::operator int()
{
    return m_iData;
}

『な、なんかこれまた変な書き方だよね……』
「書き方は、以下のようになります」

クラス::operator 型()

「こうすると、〈クラス〉が〈型〉に変換されようとしたときに、この
メンバ関数が呼び出されます」
『 m_iData を返すって事は、その値が i に渡されるんだ』
「そういうこと。こんな感じに、型変換演算子のオーバーロードは〈ただひ
とつだけメンバ変数を持っていて、それが目に見えて分かる〉ような場合に
だけ作るような感じかな」
『どゆこと?』
「メンバ変数がふたつあったら?」
『……どっち返せばいいかわからないね』
「でしょう。それよりは、 CString クラスみたいに」
『何返すのか分かり切ってる!』
「っていうクラスの方が型変換演算子のオーバーロードを使うのに向いてい
る、ってこと」
『なるほどねー。……? 質問!』
「はい火美ちゃん」
『これってメンバ関数だけど、普通の関数にはできる?』
「ううん、できません。まだ説明していなかったけど、 = 演算子とか、こ
の型変換演算子は、メンバ関数としてしか作れないんです」
『げ、そうなんだ』
「だから」

operator int( CData &p_rcData )
{
    return p_rcData.m_iData;
}

「みたいなのは作れません」
『なるほど、じゃあ次の質問!』
「はい火美ちゃん」
『さっきの使ってるとこ見て思ったんだけど』

    // 型変換演算子のオーバーロードを使用します。
    int i = cData;

『これって、わざわざ型変換演算子のオーバーロードしなくても、 
= 演算子のオーバーロードしちゃえばいいんじゃない?』
「さっき説明したけど」
『あ”、そういえばそうだね、 = 演算子はメンバ関数じゃないといけない
けど、そしたら int 型のメンバ関数にしなきゃいけなくて……無理だね』
「それ以前に、この例は = 演算子を使っているけど、 int 型変数を宣言し
ているわけだから、実際には……」
『?』
「つまり、こういうこともできるから」

    // 型変換演算子のオーバーロードを使用します。
    int i( cData );

『あ! そうだった、コンストラクタ呼んでるんだ!』
「そういうこと。変数の初期化をするときの = 演算子は、実際には引数が
1つのコンストラクタを呼び出しているのと同じこと」
『 Version 16.12 ( No.339 ) でやったのだ』
「だから、 = 演算子じゃなくて、コンストラクタの話として考えなきゃい
けないわけ」
『あー。……でも、 int 型のコンストラクタとか作れないし』
「 int 型ならね。でも普通のクラスなら」
『作れちゃう……? じゃあさじゃあさ、その普通のクラスのコンストラクタ
で CData クラス受け取ってさ、 CData クラスでは……あれ?』
「うん、つまり、その普通のクラスを CData2 だとすると」

    // 型変換演算子のオーバーロードを使用します。
    CData2 cData2 = cData;

「ってした時に、 CData2( CData &p_rcData ) が呼ばれるのか、
CData::operator CData2() が呼ばれるのか分からない、ってことでしょ?」
『……??? なんだかよく分からなくなってきた』
「……というわけで次回に続く」
『ええっ!?』

/*
    Preview Next Story!
*/
『なんで続くのー?』
「実は、これはとても重要な問題なんです」
『そなの? ちょっと思い付いただけなんだけど』
「そういうところが重要なんだよね、実は」
『意外』
「というわけで次回」
< Version 16.20 オーバーロードの選択 >
『につづく!』
「逆に、気付かないと実はすごくまずいという」
『う”、意外意外』
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。