25.1 コンストラクタ
/* コンストラクタの役割 */
省略
/* 引数のないコンストラクタ */
/* 引数がひとつのコンストラクタ */
/* 引数が複数個のコンストラクタ */
/* コンストラクタの多重定義 */
/* 引数がないときの初期化 */
省略
/* デフォルト引数のコンストラクタ */
/* デフォルトコンストラクタ */
省略
/* 暗黙のうちに用意されるデフォルトコンストラクタ */
省略
/* デフォルトコンストラクタの生成 */
/* コンストラクタと配列の初期化 */
引数が0個のコンストラクタの場合
Csmp a[3];
引数が1個のコンストラクタの場合
Csmp1 b[3] = { Csmp1(10), Csmp(20), Csmp(30) };
Csmp1 c[3] = { 10, 20, 30 };
引数が複数個のコンストラクタの場合
Csmp2 d[3] = {Csmp(70, 75), Csmp2(80, 85), Csmp2(90, 95) };
Csmp2 d[9] = {Csmp(70, 75), Csmp2(80, 85) };
/* explicit付きコンストラクタ */
暗黙の型変換を禁止し、
明示的に"Mycls"を使わせることを強制するという機能が用意されています。
それがexplicit指定子です。
この機能を使うと
Mycls dt = 10;
myfunc(10);
/* T()という記法 */
return Mycls(); // 引数のないコンストラクタを使う
return Mycls(5); // 引数のあるコンストラクタを使う
25.2 コピーコンストラクタ
/* コピーコンストラクタの記述 */
クラス名(const クラス名& obj) {
// コピー記述
}
/* 初期化と代入は異なる */
省略
25.3 デストラクタ
/* デストラクタの役割 */
省略
/* デストラクタの記述 */
/* コピーコンストラクタも用意する */
省略
/* コンストラクタとデストラクタの動作タイミング */
省略
25.4 変換コンストラクタと変換関数(変換演算子)
/* コンストラクタによる型変換 */
class XYdata {
private:
int x, y;
public:
XYdata(int n) { x = n; y = 0; } // 引数1個のコンストラクタ
XYdata(int n1, int n2) { x = n1; y = n2; } // 引数2個のコンストラクタ
というクラスがあったとき、
XYdata dt = 100;
という記述は、
100というint型データをXYdata型の(x=100, y=0)というオブジェクトに変換する
という機能を持っていることになります。
このように引数1個で呼び出すことのできるコンストラクタは型変換機能をもつことになります。
これを変換コンストラクタといいます。
/* 変換関数による型変換 */
XYdata dt(100. 200);
int a;
a = dt;
のような記述は変換関数という機能を用意しています。
変換関数の書式
operator 型() { return 式; }
25.5 thisポインタ
/* thisポインタの機能 */
void Person::setname(string s)
{
name = s;
}
をthisポインタを使って記述すると
void Person::setname(string s)
{
this->name = s;
}
となる。
/* thisポインタを活用する */
25.6 フレンド関数とフレンドクラス
/* フレンド関数を作る */
/* フレンドクラスを作る */
25.7 静的メンバ
/* 静的データメンバ */
クラス内で宣言する変数と関数にはstaticを付けることができます。
このように宣言された変数を「静的データメンバ」、関数を「静的メンバ関数」といいます。
staticを付与したデータメンバは、
そのクラス型のオブジェクトを複数宣言しても、全体でひとつだけ用意される
という特徴があります。
静的データメンバ:同じクラス型のオブジェクト間で共通して使用する変数を設定
静的メンバ関数:オブジェクト名を通さずにアクセスできる
オブジェクトが生成されなくてもアクセスできる
/* 静的メンバ関数 */
/* 静的メンバのクラス名による利用 */
省略
25.8 メンバポインタ
/* 通常ポインタとメンバポインタ */
省略
/* メンバポインタの宣言 */
クラス名がXであったとき、メンバポインタは、
X::*
という宣言子を付与して宣言します。
/* メンバポインタの利用 */
メンバポインタ設定
Mycls mm;
Mycls *pp = &mm;
dp = &Mycls::smpdt;
fp = &Mycls::smpfunc;
クラス実体とともに使うとき
mm.*dp = 123;
(mm.*fp)(100);
クラスへのポインタとともに使うとき
pp->*dp = 123;
(pp->*fp)(100);
/* typedef宣言と併用する */
// 3つのメンバポインタをtypedef宣言
typedef int MPcls::* Pdata;
typedef void (MPcls::* Pfunc0)();
typedef void (Mpcls::* Pfunc1)();
// 新しい型名で宣言
Pdata dp; // Pdata型の宣言
Pfunc0 fp0; // Pfunc0型の宣言
Pfunc1 fp1; // Pfunc1型の宣言
25.9 constメンバとmutable指定し
/* consデータメンバ */
class ClsA {
static const int aa = 100;
//static const double dd = 12.34; // 非定数はできない
enum { aa = 1234, bb = 200 }; // aaとbbは定数になる
};
/* constメンバ関数 */
constメンバ関数は、クラス内容を変更しないことを明示します。
class ClsA {
private:
int dt;
public:
ClsA(int n) { dt = n; }
void set(int n) { dt = n; } // (1)
// void set_cn(int n) const { dt = n; } // (2)
void disp_cn() const { cout << "dt=" << dt << 'n'; } // (3)
};
class ClsA {
...
void disp_cn() const;
};
void ClsA::disp_cn() const
{
cout << "dt=" << dt << 'n';
}
(1)通常のメンバ関数
(2)constメンバ関数のつもりですが、内部でメンバdtの値を変更しようとしているので、
コンパイルエラーになります。
(3)正しいconstメンバ関数です。メンバdtの値を参照しているだけなので問題ありません。
/* constメンバ関数とthisポインタ */
通常のメンバ関数set()に渡されるthis→ClsA *this
constメンバ関数disp_cn()に渡されるthis→const ClsA *this
/* constメンバ関数の利用 */
/* 仮引数に対するconst化 */
int func(const ClsA &obj) {}
/* mutable指定子 */
constが指定されているときにも、
あるデータメンバだけは変更可能にしたいという要求があります。
それを行うのが、mutable指定です。
mutableは決してconstにはできないという性格を決める指定子です。
25.10 クラスのファイル分割
/* クラスのファイル分割 */
省略
/* ファイル分割の基準 */
省略
25.11 その他の機能
/* クラス内typedef */
class Mycls {
typedef unsigned char u_char;
u_char a; // これは正しい
}
u_char b; // これはエラー。u_charはMycls内だけで使用可能
/* クラス内enum */
class Mycls2 {
enum Coltyp { red, blue, black, white };
Coltyp a; //これは正しい
};
Coltyp a; //これはエラー。ColtypはMycls内だけで使用可能
/* 空のクラス */
class SomeCls { };
SomeCls a;
/* クラス名の隠蔽と強制参照 */
int main()
{
int Person; // 変数名としてPersonを宣言すると
//Person dt; // 通常は正当なこの記述がエラーになる
class Person dt; // その場合はこのように"class"を付けると
// 正常なクラス指定になる
Person = 1234; // int変数Personに設定
dt.setage(30); // オブジェクトdtに設定
}