Cpp クラス コンストラクタ
C++に戻る
本来の表記は「C++(Cpp) クラス コンストラクタ」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。 |
※このページではC++にのみ存在する機能として、記事タイトルがC++ クラス コンストラクタになっています。
クラス コンストラクタ
コンストラクタとは、クラスが実体化されたとき、クラス変数が作られたときに自動的に呼び出される関数です。変数生成時に初期化引数を与えられた場合には、自動的に呼び出される関数が引数の形式と一致するものが呼び出されます。
クラスが作られるときに自動的に呼び出される関数?それってなんていう名前の関数なのか?とか気になると思いますが、クラス名と同じ名前の関数が呼び出されることになっています。例えば、CTestというクラスならCTest()というメンバ関数になります。基本的にはpublicのアクセス指定子を付与するのが通常です。今までのサンプルでもしれっとコンストラクタは登場していました。コンストラクタは英語でConstructorと表記されるもので、直訳としては建設者みたいな感じで擬人化された表現です。インスタラクタが教えてくれる人であるように、イントラクションしてくれる人。指示してくれる人。という表現に似ています。Construction(建設)してくれる人がConstructorです。
自動的に呼び出される関数ですが、呼び出さないようにする方法はあるのでしょうか?それはプログラムとして何も記述しなければいいだけのことです。実際には、呼び出されているのかもしれませんが、何もしないことに変わりないので、それでよしとするしかありません。ん~でも、コンストラクタ中で自分自身のクラスを呼び出したりすると再帰的に呼び出されたりして、ややこしいことになりそうです。いや、なります。最悪は無限にループします。危険です。自動で呼び出されるというのは、実に危険なことです。やっていいことと悪いことが発生します。そこは肝に銘じておかなければならないでしょう。基本的にコンストラクタは、クラスを初期化するために使います。それには、どこからか値を取得する処理をしたりすることもあれば、メンバ変数に値を代入したりすることもあると思います。クラスを使うための構築時に何かを作業するモノとしての役割を担います。よくプログラムでは構築という言葉を使うので構築者という表現のほうがピンとくる人もいるやもしれません。
では、基本的な記述方法を見ておきましょう。例えばCConstructor001というクラスを作る場合
Constructor001.h
#pragma once
class CConstructor001
{
public:
CConstructor001(void);//★1.コンストラクタ 引数無し
};
★1.部分のようにクラス名と同じ名前のメンバ関数を呼び出す感じで定義することができて、プログラムとして以下のように
Constructor001.cpp
#include "Constructor001.h"
CConstructor001::CConstructor001(void)
{
printf("■CConstructor001コンストラクタ\n");//★2.
}
のように、プログラムを記述することができます。上記のように定義することによって、メインプログラムとかから、クラスが生成されたり、作成されるとコンストラクタの関数の中のプログラムが処理され、上記の例であれば★2.部分のプログラムが実行されます。上記では引数をもたないコンストラクタを作ったので引数部には(void)と記述されています。そうするとメインプログラムでは、
Sample_main.cpp
#include "stdafx.h"
#include "Constructor001.h"
int _tmain(int argc, _TCHAR* argv[])
{
CConstructor001 CConstructor001_obj;
return 0;
}
という具合に、引数を持たない初期化方法によってクラスを作成するとコンストラクタが自動的に呼び出され、これだけの実行であってもコンストラクタが動作し、出力結果として
出力結果
■CConstructor001コンストラクタ
のような実行結果が得られます。ここまでがコンストラクタの基本です。
少し、ややこしいところに踏み込みますが、コンストラクタには引数を与えることができます。例えば、int型変数を動的に生成する場合は
int* nValue = new int(1000);
あるいは
int nValue = 1000;
あるいは
int nValue(1000);
とすると初期値を1000としてnValueというint型の変数が作成できます。これと同じようなしくみとして、コンストラクタを利用するならば、引数をとることができるコンストラクタを作成できます。そのためにプログラムを以下のように変更します。
Constructor001.h
#pragma once
class CConstructor001
{
public:
CConstructor001(void);
CConstructor001(int nValue_Para01)//★11.コンストラクタ 引数有り int型変数1つ
};
という具合に引数をとる★11.のようなコンストラクタを作ることができます。もちろんプログラム部でも、その引数を利用することができて
Constructor001.cpp
#include "Constructor001.h"
CConstructor001::CConstructor001(void)
{
printf("■CConstructor001コンストラクタ\n");
}
CConstructor001::CConstructor001(int nValue_Para01)
{
printf("■CConstructor001コンストラクタ=%d\n",nValue_Para01);//★12.
}
のように引数付きのコンストラクタを追加できます。同じ関数名であっても引数が違えば、いくつでも同じ関数を作って問題ありません。様々な引数の形式に対応しようとすれば、コンストラクタは複雑さを増してきます。通常はテンプレート関数やテンプレートクラスという手法を使って、様々な引数をとることができるようなプログラムを作成しますが、そのことについてはテンプレートの項目で解説したいと思います。
int型の引数をとるコンストラクタを作成しましたので、以下のような感じでクラス変数や実体を作るような処理の初期化が実施できるようになります。3つめの代入するような記述方法では、複数の引数を設定できないので、少し特殊な初期化になってしまいます。配列を初期値に渡せる場合は配列の初期化のような記述もできるでしょう。
- CConstructor001* CConstructor001_Instance = new CConstructor001(1);
- CConstructor001 CConstructor_obj(1);
- CConstructor001 CConstructor2_obj = 1;
いろいろな引数のコンストラクタを定義することのサンプルの説明については省略しますが、引数の個数によって処理を変える場合は、選択されるコンストラクタの関数の各処理で不具合が怒らないように慎重に作らなければならないことに注意が必要です。引数の個数によってまったくことなるプログラムが実行されるということを覚えておきましょう。こういった同じ関数名で引数の種類だけをかえた関数を作ることもオーバロードと表現することがあります。オーバロードを活用する手法については議論や検討やさらなる学習が必要になると思います。
C++に戻る