3章 クラス
3-1 const
メソッドについて
const
メソッドconst
変数- 書き換えができないメンバ変数
- メンバ初期化子、もしくはメンバ初期化リストでのみ初期化することができる
- https://wandbox.org/permlink/yIAc4PQpkqT6ji3p
3-2 コンストラクタ、デストラクタ
3-3 初期値を受け取るコンストラクタ
- 何も定義しないとデフォルトコンストラクタがコンパイラにより作成される
- コンストラクタ内で他のコンストラクタを呼び出す機能を移譲コンストラクタとよぶ
- 一般には、移譲先にコンストラクタの実装の大部分を任せる
- 移譲元ではメンバ変数の初期化も行えない
- 多くの場合はコンパイラが自動生成するコピーコンストラクタをそのまま使えば良い
- メンバ変数にポインタを持つ場合など、デフォルトのコピーコンストラクタだと、コピー先も同じオブジェクトを指し示すことになってしまう→デストラクタでの2重解放などを誘発
- そういう場合はユーザーが記述するコピーコンストラクタを自分で実装する
- https://wandbox.org/permlink/8Kh4ZxmMatTWr3ZB
- コピーコンストラクタがいつ呼ばれるのかについてはhttps://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/C++2/09/09-03.html
- 代入演算子と中括弧で暗黙のコンストラクタ呼び出しが行える
3-4 デフォルトの初期値
- クラス定義内でのメンバ変数の初期化の構文を非静的メンバ変数の初期化子(Non Static Data Member Initializer : NSDMI)と呼ぶ
- NSDMIと呼ばれることが多い
- 構文は下記
class A
{
type1 var1 = defVal1;
type2 var2 = {defVal2};
type1 var3(defVal3);
type1 var4{defVal4};
};
- メンバー初期化子リストも与えられた場合はメンバー初期化リストが優先される
3-5 継承
- ベースとなるクラスを基底クラス、基底クラスを継承したクラスを派生クラスとよぶ
- 「クラスAから派生したクラスBが、基底クラスの機能を継承する」といいた言い回し
- 構文は下記
class derived-class-name : access-specifier base-class-name { ... };
access-specifier
を省略するとprivate
になる- privateの場合、基底クラスのメンバに派生クラスからアクセスできなくなる
- 基底クラスのメンバ関数の処理内容を派生クラスで変更することができる
- 基底クラスのメンバ関数は
virtual
を指定し、仮想関数にすることで、派生クラスで処理内容の変更を許可する - 派生クラスでは
override
指定子を追加し、処理内容を書き換える- 派生クラスで何もoverrideしなければ、自動的に基底クラスの仮想関数を継承する
- overrideする場合は戻り値の型、関数名、
const
の有無なども一致させる必要がある - 実は基底クラスで
virtual
を指定しておけば、派生クラスのoverride
は省略できるが、わかりにくくなるので避ける
- 基底クラスのメンバ関数は
- 派生クラスで基底クラスと同名のメンバ関数を作成すると名前の隠蔽(name hiding)が生じる
- 派生クラスにオーバーライドを強制するメソッドを純粋仮想関数とよぶ
3-6 オブジェクトポインター
- 構造体と同じく、ポインタを経由してメンバにアクセスするときはアロー演算子
->
を使う - メンバ関数の仮引数とメンバ変数名が一致するとき、その変数名は仮引数として解釈される
- メンバ変数にアクセスするときには、
this
ポインタを経由してアクセスする this
ポインタは書き換え不可const
メンバ関数の中ではthis
ポインタはconstポインタとなる
- メンバ変数にアクセスするときには、
3-7 クラス、構造体、共用体の関係性
- 構造体
- クラスと構造体は、デフォルトのアクセス指定だけが異なる
- クラスは
private
、構造体はpublic
- 基底クラス(構造体)から派生するときのアクセス指定もクラスが
private
で構造体がpublic
- 他に違いは無いが、Cからの名残で単にデータの箱をつくるときは構造体を用いることが多い
- 共用体
- 無名共用体
class Hoge { public: union { int a; float b; } };
3-8 friend
関数
- メンバ関数でないにもかかわらず、
private
なメンバにアクセスできるような関数を用意したい場合は、フレンド関数を使用する- フレンド関数はクラス宣言内で
friend
をつけたものをプロトタイプ宣言する(フレンド宣言) - メンバ関数ではないので、引数としてクラスのポインタや参照を一つ以上受け取るのが一般的
- 複数クラスの非公開メンバにアクセスしたい場合は、複数クラスでフレンド宣言する
- 定義には
friend
は不要
- フレンド関数はクラス宣言内で
- フレンド宣言はクラスの外側では行えない
3-9 static
クラスメンバ
static
メンバ変数static
メンバ関数
class A { public: static int stVal; } ; int A::stVal = 3;