「C++の基礎 - コンストラクタ」の版間の差分
ナビゲーションに移動
検索に移動
編集の要約なし
(ページの作成:「== 概要 == 自動生成されるコンストラクタは、デフォルトコンストラクタの他にコピーコンストラクタがある。 == デフォルト…」) |
編集の要約なし |
||
1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
自動生成されるコンストラクタは、デフォルトコンストラクタの他にコピーコンストラクタがある。 | 自動生成されるコンストラクタは、デフォルトコンストラクタの他にコピーコンストラクタがある。<br> | ||
<br><br> | |||
== デフォルトコピーコンストラクタ == | == デフォルトコピーコンストラクタ == | ||
CMyClassのインスタンスを引数にして、新しいCMyClassのインスタンスを生成することができる。 | CMyClassのインスタンスを引数にして、新しいCMyClassのインスタンスを生成することができる。<br> | ||
clsMyClass2の中身を確認すると、clsMyClass1と同じ値になる。 | clsMyClass2の中身を確認すると、clsMyClass1と同じ値になる。<br> | ||
これは、デフォルトコピーコンストラクタというものが自動的に生成されるからである。 | これは、デフォルトコピーコンストラクタというものが自動的に生成されるからである。<br> | ||
デフォルトコピーコンストラクタは、自分と同じクラスのインスタンスを引数とするコンストラクタで、 | デフォルトコピーコンストラクタは、自分と同じクラスのインスタンスを引数とするコンストラクタで、<br> | ||
メンバ変数をすべてコピーしたものが新しく生成される。 | メンバ変数をすべてコピーしたものが新しく生成される。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
#include <iostream> | #include <iostream> | ||
52行目: | 52行目: | ||
== デフォルトコピーコンストラクタが使用できないケース == | == デフォルトコピーコンストラクタが使用できないケース == | ||
デフォルトコピーコンストラクタは便利であるが、過信していると致命的なバグの原因となる場合がある。 | デフォルトコピーコンストラクタは便利であるが、過信していると致命的なバグの原因となる場合がある。<br> | ||
<br> | |||
下記のソースコードにおいて、メンバ変数にポインタを持つクラスの場合、 | 下記のソースコードにおいて、メンバ変数にポインタを持つクラスの場合、<br> | ||
デフォルトコピーコンストラクタが実行されると、このポインタのアドレス値もコピーされる。 | デフォルトコピーコンストラクタが実行されると、このポインタのアドレス値もコピーされる。<br> | ||
つまり、clsMyClass1とclsMyClass2の*m_piNumberが指すアドレスはどちらも同じになる。 | つまり、clsMyClass1とclsMyClass2の*m_piNumberが指すアドレスはどちらも同じになる。<br> | ||
clsMyClass2を通してm_piNumberの値を変更すると、無関係のclsMyClass1にも影響が出てしまう。<br> | |||
このような場合には、デフォルトコピーコンストラクタを使用してはいけない。<br> | |||
<source lang="c++"> | <source lang="c++"> | ||
#include <iostream> | #include <iostream> | ||
96行目: | 96行目: | ||
== コピーコンストラクタの定義 == | == コピーコンストラクタの定義 == | ||
これを解決するには、自分でコピーコンストラクタを定義する。 | これを解決するには、自分でコピーコンストラクタを定義する。<br> | ||
<br> | |||
コピーコンストラクタは、自身のインスタンスの参照を引数に取るコンストラクタである。 | コピーコンストラクタは、自身のインスタンスの参照を引数に取るコンストラクタである。<br> | ||
コピーコンストラクタで、コピーしたいメンバ変数を任意に選択することができる。 | コピーコンストラクタで、コピーしたいメンバ変数を任意に選択することができる。<br> | ||
ただし、このままだとメンバ変数が勝手にコピーされないだけで、デフォルトコピーコンストラクタを呼び出すことができる。 | ただし、このままだとメンバ変数が勝手にコピーされないだけで、デフォルトコピーコンストラクタを呼び出すことができる。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
class CMyClass | class CMyClass | ||
135行目: | 135行目: | ||
== コピーコンストラクタの禁止 == | == コピーコンストラクタの禁止 == | ||
上記の場合には、コピーコンストラクタ自体を禁止するとよい。 | 上記の場合には、コピーコンストラクタ自体を禁止するとよい。<br> | ||
コピーコンストラクタをprivateに記述することで、外部からはアクセスできない状態にする。 | コピーコンストラクタをprivateに記述することで、外部からはアクセスできない状態にする。<br> | ||
そのため、コピーコンストラクタを使用した時点でコンパイラがエラーを出すので、コーディング時にエラーに気付くことができる。 | そのため、コピーコンストラクタを使用した時点でコンパイラがエラーを出すので、コーディング時にエラーに気付くことができる。<br> | ||
<br> | |||
なお、この方法で禁止できるのはコピーコンストラクタの使用であり、代入操作は禁止されない。 | なお、この方法で禁止できるのはコピーコンストラクタの使用であり、代入操作は禁止されない。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
class CMyClass | class CMyClass | ||
169行目: | 169行目: | ||
== 変換コンストラクタ == | == 変換コンストラクタ == | ||
引数が1つだけのコンストラクタは、以下のようにして呼び出すことが可能である。 | 引数が1つだけのコンストラクタは、以下のようにして呼び出すことが可能である。<br> | ||
<br> | |||
clsMyClassはCMyClassのインスタンスなのに、整数をそのまま代入することが出来る。(暗黙的な呼び出し) | clsMyClassはCMyClassのインスタンスなのに、整数をそのまま代入することが出来る。(暗黙的な呼び出し)<br> | ||
1つの引数で呼び出せるコンストラクタは変換コンストラクタとして動作することができる。 | 1つの引数で呼び出せるコンストラクタは変換コンストラクタとして動作することができる。<br> | ||
<br> | |||
変換コンストラクタは、与えられた値の暗黙的な変換が可能な場合、値からインスタンスを生成する。 | 変換コンストラクタは、与えられた値の暗黙的な変換が可能な場合、値からインスタンスを生成する。<br> | ||
変換ができない場合は、インスタンスを生成することは出来ない。 | 変換ができない場合は、インスタンスを生成することは出来ない。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
class CMyClass | class CMyClass | ||
219行目: | 219行目: | ||
== 変換コンストラクタの禁止 == | == 変換コンストラクタの禁止 == | ||
変換コンストラクタは便利であるが、以下のような問題もある。 | 変換コンストラクタは便利であるが、以下のような問題もある。<br> | ||
<br> | |||
関数funcはCMyClassのインスタンスを受け取るつもりで作成した関数である。 | 関数funcはCMyClassのインスタンスを受け取るつもりで作成した関数である。<br> | ||
この関数は引数に整数を指定して呼び出すことが出来る。 | この関数は引数に整数を指定して呼び出すことが出来る。<br> | ||
これは、引数に指定した整数が関数funcに渡された時点で、CMyClassの変換コンストラクタが動作して、 | これは、引数に指定した整数が関数funcに渡された時点で、CMyClassの変換コンストラクタが動作して、<br> | ||
CMyClassのインスタンスが生成されるためである。 | CMyClassのインスタンスが生成されるためである。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
class CMyClass | class CMyClass | ||
247行目: | 247行目: | ||
</source> | </source> | ||
<br> | <br> | ||
この動作を意図していない場合が多い。 | この動作を意図していない場合が多い。<br> | ||
そのため、このような場合は、変換コンストラクタを禁止することが出来る。 | そのため、このような場合は、変換コンストラクタを禁止することが出来る。<br> | ||
<br> | |||
コンストラクタの前にexplicitキーワードを付けると、暗黙的な呼び出しを禁止することが出来る。 | コンストラクタの前にexplicitキーワードを付けると、暗黙的な呼び出しを禁止することが出来る。<br> | ||
変換コンストラクタは意図しない動作となることが多いので、基本的に禁止しておいた方がよい。 | 変換コンストラクタは意図しない動作となることが多いので、基本的に禁止しておいた方がよい。<br> | ||
<source lang="c++"> | <source lang="c++"> | ||
class CMyClass | class CMyClass |