Cpp クラス コピーコンストラクタ 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(クラス コピーコンストラクタ)
20行: 20行:
 
クラスの変数を代入演算子をつかって以下のように表現しようとしたとすると、
 
クラスの変数を代入演算子をつかって以下のように表現しようとしたとすると、
  
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
CTest CTest1_obj;
 
CTest CTest1_obj;
 
CTest CTest2_obj = CTest1_obj;
 
CTest CTest2_obj = CTest1_obj;
</syntaxhighlight>
+
</syntaxhighlight2>
  
 
という代入は、コピーコンストラクタという仕組みがない場合には、通常期待する代入とは違った動作になってしまいます。CTest2_objの値はCTest1_objと確かに同じ値を保持することになりますが、単純にCTest1_objと同じアドレスを保持することになるだけで、CTest1_objの保持している値と連動してしまいます。動的に生成されたクラス変数ならば、CTest1_objが消えれば、CTest2_objは実体の存在しないアドレスを保持していることになり、CTest2_objの保持するアドレス値をnull_ptrにするといったような細かい調整をしない限り、CTest2_objのデストラクタと呼ばれるクラス変数消滅時に必ず動作する処理で実体を消す処理がうまくいかずプログラムは異常終了します。
 
という代入は、コピーコンストラクタという仕組みがない場合には、通常期待する代入とは違った動作になってしまいます。CTest2_objの値はCTest1_objと確かに同じ値を保持することになりますが、単純にCTest1_objと同じアドレスを保持することになるだけで、CTest1_objの保持している値と連動してしまいます。動的に生成されたクラス変数ならば、CTest1_objが消えれば、CTest2_objは実体の存在しないアドレスを保持していることになり、CTest2_objの保持するアドレス値をnull_ptrにするといったような細かい調整をしない限り、CTest2_objのデストラクタと呼ばれるクラス変数消滅時に必ず動作する処理で実体を消す処理がうまくいかずプログラムは異常終了します。
34行: 34行:
  
 
CopyConstructor001.h
 
CopyConstructor001.h
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#pragma once
 
#pragma once
 
class CCopyConstructor001
 
class CCopyConstructor001
47行: 47行:
 
   ~CCopyConstructor001(void);
 
   ~CCopyConstructor001(void);
 
};
 
};
</syntaxhighlight>
+
</syntaxhighlight2>
 
CopyConstructor001.cpp
 
CopyConstructor001.cpp
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include "stdafx.h"
 
#include "stdafx.h"
 
#include "CopyConstructor001.h"
 
#include "CopyConstructor001.h"
64行: 64行:
 
}
 
}
  
CConstructor001::~CConstructor001(void)
+
CCopyConstructor001::~CConstructor001(void)
 
{
 
{
 
}
 
}
  
</syntaxhighlight>
+
</syntaxhighlight2>
 +
 
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
int Look(CCopyConstructor001 objArgCCopyConstructor001){
 +
    //
 +
    return 1;
 +
}
 +
 
 +
int main(){
 +
  CCopyConstructor001 objCCopyContsructor001;
 +
  iNum = Look(objCCopyContsructor001);
 +
  return 1;
 +
}
 +
</syntaxhighlight2>
  
 
参照型の引数によって、メインプログラム側で引数に設定されたクラスの各メンバ変数の値を取得できるため、コピーコンストラクタの中で、各メンバ変数の値を引数によって得られたクラスのメンバ変数とメンバ変数との間で、初期化の処理をする仕組みです。コピーコンストラクタの関数内では、この参照の仕組みをつかってコピーのための処理を記述できると考えてよいと思います。
 
参照型の引数によって、メインプログラム側で引数に設定されたクラスの各メンバ変数の値を取得できるため、コピーコンストラクタの中で、各メンバ変数の値を引数によって得られたクラスのメンバ変数とメンバ変数との間で、初期化の処理をする仕組みです。コピーコンストラクタの関数内では、この参照の仕組みをつかってコピーのための処理を記述できると考えてよいと思います。
 +
 +
 +
 コピーコンストラクターがあれば、値渡しになっていたLook関数があっても、同じ実体を指し示すアドレスのコピーが作られ、デストラクタが呼び出されても、main関数で生成したオブジェクトのアドレスそのものではないし、Look関数に渡された引数にぶら下がっている参照変数からのメンバ変数も参照というカタチをとることになるため、Look関数が終わっても、参照型引数としてコピーして作られた方の引数クラスと同じ形式の参照型変数のアドレスやLook関数内で使ったその他のオブジェクトが消滅するだけなので、元々のmainクラスから作られたクラスの先頭アドレスにぶら下がっている実体が残っているため、main関数が終わるときに、きちんとmain関数で生成したクラスが消滅するため、問題が発生しません。そして関数の引数としても問題がなく、より役立つクラスになります。コピーコンストラクタは大事だよ。
  
  

2020年7月10日 (金) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス