第27章 暗黙の了解

 第9章でオブジェクトを値渡しするプログラムをやりました。誰かここに int 型の値を入れた人はいませんか? 今回はそんな話です。


 今回の要点です。


 では、いってみましょう。


 早速、次のプログラムを見て下さい。

プログラム
// Copy1b.cpp
#include <iostream.h>
#include "IntArray.h"

void Disp(CIntArray array)
{
    int i;

    for(i = 0; i < array.NumOf(); i++)
        cout << array.Get(i) << ' ';
    cout << endl;
}

int main()
{
    CIntArray arrayAtoZ('Z' - 'A' + 1);
    int       i;

    for(i = 0; i < arrayAtoZ.NumOf(); i++)
        arrayAtoZ.Set(i, 'A' + i);
    Disp(arrayAtoZ);
    Disp(i);

    return 0;
}
実行結果
コンストラクタが呼ばれました。要素数は 26 です。
コピーコンストラクタが呼ばれました。
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 
デストラクタが呼ばれました。要素数は 26 でした。
コンストラクタが呼ばれました。要素数は 26 です。
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
デストラクタが呼ばれました。要素数は 26 でした。
デストラクタが呼ばれました。要素数は 26 でした。

 第9章の Copy1.cpp に近いですね。しかし、最後に変なものが付いています。

Disp(i);

 そうです。これです。

 Disp 関数は CIntArray 型の引数をとるはずなのに、何と、int 型の変数を渡しています。しかも、エラーが出ていません

 何とも不思議なことですが、実行結果を見てみるとどうなっているかが推測できます。

 この1行を書かなかったときに表示される結果は、上の赤い3行を消したものになります。つまり、上の赤い3行は Disp(i); を実行したときに表示されたということになります。

 ここで、「コンストラクタが呼ばれました。要素数は 26 です。」というのが、先ず表示されています。これが表示されるのは CIntArray(const int nNumOf); の中だけのはずです。ということは、CIntArray(const int nNumOf); が呼ばれているということになります

 そして、ここで double 型の変数を渡すと「'double' から 'const int' に変換しました。」というエラーが出ます。

 そして、要素数はその時の i の値と同じ26です。

 これらのことを併せて考えると、どうも「i を使って CIntArray(const int nNumOf); が呼ばれた」ということになりそうです。つまり、

CIntArray array(i);

としたときと同じ事をしているわけです。

 このように、引数ではコピーコンストラクタだけではなく、別のコンストラクタも呼ばれるのです

 この機能はいろいろなところで活用できます。例えば、文字列を扱うクラスを作ったとします。

 このクラスのコンストラクタには「文字列を渡して、そのコピーを作る」というものがあるでしょう。こういうとき、値渡しの引数に文字列を直接渡しても一向に構わないということになります。いちいちオブジェクトを作って、それを渡さなくても構わないわけです。

 ほかにも、いろいろなところで活用できることがあると思います。


 しかし、逆にこういった機能が欲しくないときもあります。今がその時で、引数に int 型の変数を入れたとしても特に意味はありません。こんな使い方はしないでしょうから、エラーが出てくれた方がいいですね。

 そういうときは、コンストラクタの宣言の頭に explicit をつけます。

プログラム
// IntArray.h
class CIntArray
{
public:
    explicit CIntArray(const int nNumOf);
};
エラーコード
copy1.cpp(22) : error C2664: 1 番目の引数を 'int' から 'class CIntArray' に変換できません。

 これで Disp(i); でエラーが出るようになりました。安心ですね。

 あと、まぁ考えれば分かると思いますが、値渡しで呼ばれる可能性のあるコンストラクタは、引数が1つのものだけです。デフォルトコンストラクタや、引数の2つ以上あるコンストラクタは呼ばれません。呼びようがない、というのが正しいかもしれませんね。


 では、今回の要点です。


 それでは、次回まで。


第26章 これ。2 | 第28章 静かなるメンバ

Last update was done on 2000.9.1

この講座の著作権はロベールが保有しています