#pragma twice

KAB-studio > プログラミング > #pragma twice > 339 Version 16.12 コピーコンストラクタを作る

#pragma twice 339 Version 16.12 コピーコンストラクタを作る

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

 Version 16.12
コピーコンストラクタを作る

今回は、前回説明したコピーコンストラクタの作り方について説明します
メンバ変数の中身をコピーしてくれるコンストラクタなんだよね
そうなんだけど、コピーコンストラクタを作ったら、そのコピーの処理は
自分で書かなきゃいけないんです
げ、それ面倒
だから、単にコピーするだけならコピーコンストラクタを作る必要はない
かな。コピー時に特別な処理が必要な時だけコピーコンストラクタを作る、
っていうのがいいかな
りょーかい
さて、では実際にコピーコンストラクタを作ってみます。まずクラスの
宣言の側

// Data.h

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

public:
    // 引数のないコンストラクタ。
    CData();

    // コピーコンストラクタ。
    CData( const CData &p_rcData );
};

あれ? コピーコンストラクタって…… CData クラスの、const 参照な
んだ

    // コピーコンストラクタ。
    CData( const CData &p_rcData );

そう、これは仕様として決められているから変えられません。それに、前
回説明したように、以下のようにして渡せないといけないから

    // もうひとつ CData クラスの変数を宣言します。
    // コピーコンストラクタでコピーします。
    CData cData2( cData );

そか、普通に渡せなきゃいけないから自分のクラスの参照になるんだね。 
const なのは書き換え不可にするから?
そういうこと。コピー元が書き換わっちゃ意味ないからね。次に、この時
呼ばれるコピーコンストラクタの定義の方を見てみます

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

#include "Data.h"

// 引数のないコンストラクタ。
CData:: CData()
    : m_iData( 0 )
{
}

// コピーコンストラクタ。
CData:: CData( const CData &p_rcData )
    : m_iData( p_rcData.m_iData )
{
    // テスト用に出力します。
    char pch[256];
    sprintf( pch, "CData::CData( const CData & ):%d\n", m_iData );
    OutputDebugString( pch );
}

コピーコンストラクタは以下の部分

// コピーコンストラクタ。
CData:: CData( const CData &p_rcData )
    : m_iData( p_rcData.m_iData )
{
    // テスト用に出力します。
    char pch[256];
    sprintf( pch, "CData::CData( const CData & ):%d\n", m_iData );
    OutputDebugString( pch );
}

この関数の中身は、テスト用に出力している箇所だから本当は必要ないか
らね
ってことは、必要なのは

CData:: CData( const CData &p_rcData )
    : m_iData( p_rcData.m_iData )
{
}

ってことね。引数で自クラスの const 参照受け取って、メンバ変数の 
m_iData をコピー……あ、これがコピーしてるとこなんだ
そういうこと。これをしないと、コピーコンストラクタが呼ばれているの
にデータがコピーされていない、ってことになるから注意してね
はーい
あとは引数を持つコンストラクタと同じ。引数が自クラスの const 参照
っていうところだけが他のコンストラクタとの違いだね
そう考えると特に難しくないね……あ、質問!
はい火美ちゃん
引数のないコンストラクタってなんであるの? 省略してもいい?
ううん、前回説明したように引数を持つコンストラクタを省略すると
あ、デフォルトコンストラクタが消えちゃう!
だから、代わりに引数のないコンストラクタを作らなきゃいけないんで

それはコピーコンストラクタでも同じってことなのね……んー
どうしたの?
ううんなんでもない。で、使用例はどんな感じ
うん、使用例と出力結果は以下のようになります

// 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;
    cData.m_iData = 100;

    // もうひとつ CData クラスの変数を宣言します。
    // コピーコンストラクタでコピーします。
    CData cData2( cData );
    // CData::CData( const CData & ):100

    // 出力します。
    char pch[256];
    sprintf( pch, "%d\n", cData2.m_iData );
    OutputDebugString( pch );
    // 100
}

コピーコンストラクタの使い方は、前回のと同じだね

    // もうひとつ CData クラスの変数を宣言します。
    // コピーコンストラクタでコピーします。
    CData cData2( cData );
    // CData::CData( const CData & ):100

ちゃんと作ったコンストラクタが呼ばれてるね
そこが重要。自動的に作られたコピーコンストラクタと同じように、作成
したコピーコンストラクタがちゃんと呼ばれてるってこと
…………
? どうしたの?
……質問!
はい火美ちゃん
今さ、その自動的に作られたコピーコンストラクタの代わりに呼ばれたっ
て言ったけど……それってさ、単に、自クラスの const 参照を引数に持つ
コンストラクタが呼ばれた、ってだけじゃないの?
あ、そう見えちゃうよね
見えちゃうっていうか、そうじゃないの? ってゆーか、もしかして
コピーコンストラクタっていうものが存在しないんじゃないの?
そんなことはないよ。たとえば、コピーコンストラクタは以下のようにし
て使うことができるんです

    // もうひとつ CData クラスの変数を宣言します。
    // コピーコンストラクタでコピーします。
    CData cData2 = cData;
    // CData::CData( const CData & ):100

…… = で渡してる?
引数を持つコンストラクタの時に説明したけど
あ! そういえば、あのとき = で、引数ひとつのコンストラクタを呼び
出せるって……
それと同じ。そのとき、自クラスを渡すとコピーコンストラクタが呼び出
されるんです
そして……この = の時も、ちゃんとコピーコンストラクタが呼び出され
てる!
そういうこと。まとめると以下のようになります

・クラス型変数の初期化時に同じクラスの変数を渡すとコピーコンストラクタ
 が呼び出される。

・コピーコンストラクタは初めから存在する。

自クラスの const 参照を引数に持つコンストラクタを作ると、それが
 コピーコンストラクタになる。

ふ、複雑……
コピーコンストラクタっていう見えないコンストラクタがあって、それを
自クラスの const 参照で作ることができる、っていうところが難しいかも
ね。見えない所だし
見えないものは難しいよ……

/*
    Preview Next Story!
*/
……なんか、この前の const といい、難しくなってきたね……
でしょう
でしょう、じゃねー!!
でももっと難しくなるよ
うそー
でもその前に復習から
なんだ良かったー
というわけで次回
< Version 16.13 オーバーロードの復習 >
につづく!
ほら、甘いものの前に酸っぱいものをって
ダメじゃん!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。