#pragma twice

KAB-studio > プログラミング > #pragma twice > 341 Version 16.14 コンストラクタのオーバーロード

#pragma twice 341 Version 16.14 コンストラクタのオーバーロード

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

 Version 16.14
コンストラクタのオーバーロード

「前回はオーバーロードについて説明しました」
『関数は、同じ名前で引数の違う関数を作れる、と』
「そして渡した引数でどの関数が呼ばれるかが決まる、というわけです」
『それだけなら簡単よね』
「それだけなら、ね」
『う”』
「というわけで、まずはコンストラクタのオーバーロードについて説明しま
す」
『コンストラクタのオーバーロード、引数の違うコンストラクタ……ん?』
「そう、実はこれまでの例で何度も出てきています。ここまでで説明してき
たコンストラクタの復習も兼ねて見ていきます」

// Data.h

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

public:
    // 引数のないコンストラクタ。
    CData();
    // コピーコンストラクタ。
    CData( const CData &p_rcData );
    // 引数が int 型のコンストラクタ。
    CData( int p_i );
    // 引数が int 型2つのコンストラクタ。
    CData( int p_i1, int p_i2 );
};


// 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 )
{
}

// 引数が int 型のコンストラクタ。
CData::CData( int p_i )
    : m_iData( p_i )
{
}

// 引数が int 型2つのコンストラクタ。
CData::CData( int p_i1, int p_i2 )
    : m_iData( p_i1 + p_i2 )
{
}


「全部で4つのコンストラクタがあります」

・引数のないコンストラクタ
・コピーコンストラクタ
・引数が int 型のコンストラクタ
・引数が int 型2つのコンストラクタ

『あれ? デフォルトコンストラクタはないの?』
「ないよ」
『……あー、そりゃそうだよね、コンストラクタ作ったらなくなっちゃうん
だから』
「そういうこと。デフォルトコンストラクタは〈コンストラクタがない時に
だけ存在する見えないコンストラクタ〉だから、コンストラクタがあったら
ないし、あっても見えないから」
『ここに出てくるわけないね……』
「話を戻すと、このようにコンストラクタも、他のメンバ関数と同じように
オーバーロードすることができます」
『でも、コンストラクタって関数を呼ぶ、って感じじゃないからいまいち
実感が沸かないかも』
「それは言えるかもね。使用例はこうなります」

// 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 cData2( cData );
    // int 型引数を持つコンストラクタを呼び出します。
    CData cData3( 100 );
    // int 型引数2つを持つコンストラクタを呼び出します。
    CData cData4( 100, 200 );

    return 0;
}

「渡す初期値によって、コンストラクタが変わる感じかな」

・何も渡さない               → 引数のないコンストラクタ
・同じクラス                 → コピーコンストラクタ
・int型変数や整数リテラル    → 引数が int 型のコンストラクタ
・int型変数や整数リテラル2つ → 引数が int 型2つのコンストラクタ

「このように、何を渡すかによって呼ばれるコンストラクタが変わることに
なります」
『これも、他のオーバーロードと同じように、渡した型に近いものが選ばれ
るの?』
「そう。型が同じならその方、ないなら近い型のメンバ関数が呼ばれます。
どれか分からない場合にはコンパイルエラーになります」
『前回のと同じってわけね。……質問!』
「はい火美ちゃん」
『引数のないコンストラクタを呼んでる所って、こうじゃダメ?』

    // 引数のないコンストラクタを呼び出します。
    CData cData();

「だめなんです」

    CData cData();
    // コンパイルエラー:
    // error C2664: '__thiscall CData::CData(const class CData &)' : 
    // 1 番目の引数を 'class CData (__cdecl *)(void)' から 
    // 'const class CData &' に変換できません。 
    // 理由: 'class CData (__cdecl *)(void)' から 'const class CData' 
    // へは変換できません。
    // コンストラクタはソース型を持てません、またはコンストラクタの
    // オーバーロード レゾリューションがあいまいです。

『な、なんかよく分からないエラーが……』
「実際、これはできるようにして欲しかったんだけど、仕様上できないんだ
よね。だから諦めるしかないかな」
『むー……あ、もうひとつ質問!』
「はい火美ちゃん」
『 = 使ってもできるんだよね、コンストラクタ呼ぶの』
「はいできます」

// 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 cData2 = cData;
    // int 型引数を持つコンストラクタを呼び出します。
    CData cData3 = 100;
    // int 型引数2つを持つコンストラクタを呼び出します。
    CData cData4( 100, 200 );

    return 0;
}

「このように、引数がひとつのコンストラクタのみ、 = 演算子で初期化す
ることができます。してることは、さっきの例と同じだからね」
『これでコンストラクタが呼ばれるっていうのも不思議だよね……』
「 C++言語の仕様は不思議なところ多いからね」
『だよね、コピーコンストラクタだって、とっても特別なコンストラクタ
って気がするんだけど、なんか他のコンストラクタと同じような感じだよ
ね』
「そういうものが多いかも。普通のプログラムのように見えて、特別な意味
があるあるものとか」
『そういうのがよく分からない……』
「それはもう、片っ端から試してみて、コンパイルエラーを取り除きながら
憶えていくしかないかもね」
『う”……』

/*
    Preview Next Story!
*/
『こういう、特別な意味のって難しい……』
「普通のメンバ関数に見えるからね」
『そうそう。少し違うとダメだし、憶えてないといけないし』
「その一番典型的な例が演算子のオーバーロードかな」
『あーあれもよく分からなかった!』
「というわけで次回」
< Version 16.15 演算子のオーバーロードの復習 >
『につづく!』
「復習だけど、コンストラクタの例とかを踏まえつつ、だといいかも」
『そういえばそういうとこ似てる感じ……?』
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。