c++クラスの構造関数の詳細
c++クラスの構造関数の詳細
一、構造関数は何をしているのか
クラスオブジェクトが作成されると、コンパイルシステムオブジェクトはメモリ領域を割り当て、コンストラクション関数を自動的に呼び出します->コンストラクション関数によってメンバーの初期化作業を完了します
eg: Counter c1;
コンパイルシステムは、オブジェクトc 1の各データメンバー(m_value)にメモリ空間を割り当て、コンストラクタCounter()を呼び出してオブジェクトc 1のm_を自動的に初期化するvalue値を0に設定
したがって、
コンストラクション関数の役割:オブジェクトのデータ・メンバーを初期化します.
二、構造関数の種類
次に、上記で定義したクラスオブジェクトを使用して、各コンストラクション関数の使用方法を説明します.
三、思考とテスト
1.複製構造関数を注意深く観察する
なぜ関数でオブジェクトcのプライベートメンバーに直接アクセスできるのですか?
2.問題に挑戦し、引用と伝達値の違いを理解する
四、付録(浅いコピーと深いコピー)
前述したように、カスタムレプリケーションコンストラクション関数がない場合、デフォルトのレプリケーションコンストラクション関数が作成されますが、システムが作成したデフォルトのレプリケーションコンストラクション関数は、コピーされたオブジェクトのデータ・メンバーの値を新規作成されたペアに割り当てる「浅いコピー」のみを実行します.このクラスのデータ・メンバーにポインタ・メンバーがある場合、新しいオブジェクトのポインタが指すアドレスがコピーされたオブジェクトのポインタが指すアドレスと同じになり、deleteポインタをdeleteするとdeleteが2回繰り返されてエラーが発生します.次に例を示します.
【浅いコピーと深いコピー】
一、構造関数は何をしているのか
<span style="font-size:18px;">class Counter
{
public:
// Counter
// : ,
Counter()
{
m_value = 0;
}
private:
//
int m_value;
}</span>
クラスオブジェクトが作成されると、コンパイルシステムオブジェクトはメモリ領域を割り当て、コンストラクション関数を自動的に呼び出します->コンストラクション関数によってメンバーの初期化作業を完了します
eg: Counter c1;
コンパイルシステムは、オブジェクトc 1の各データメンバー(m_value)にメモリ空間を割り当て、コンストラクタCounter()を呼び出してオブジェクトc 1のm_を自動的に初期化するvalue値を0に設定
したがって、
コンストラクション関数の役割:オブジェクトのデータ・メンバーを初期化します.
二、構造関数の種類
<span style="font-size:18px;">class Complex
{
private :
double m_real;
double m_imag;
public:
//
// , , ,
// , , ,
Complex(void)
{
m_real = 0.0;
m_imag = 0.0;
}
// ( )
// , , ( c++ )
// : Complex( int num)
//
Complex(double real, double imag)
{
m_real = real;
m_imag = imag;
}
// ( )
// , ,
// , , , , “ ” 、“ ”
Complex(const Complex & c)
{
// c
m_real = c.m_real;
m_img = c.m_img;
}
// ,
// : double Complex
Complex::Complex(double r)
{
m_real = r;
m_imag = 0.0;
}
//
// , , = , ,
// = , = ,
Complex &operator=( const Complex &rhs )
{
// , ,
if ( this == &rhs )
{
return *this;
}
//
this->m_real = rhs.m_real;
this->m_imag = rhs.m_imag;
//
// eg: a=b=c b=c
// a= ( b=c , c b )
return *this;
}
};
</span>
次に、上記で定義したクラスオブジェクトを使用して、各コンストラクション関数の使用方法を説明します.
<span style="font-size:18px;">void main()
{
// , 0.0
Complex c1,c2;
// ,
Complex c3(1.0,2.5);
//
Complex c3 = Complex(1.0,2.5);
// c3 c1
// c1 ,
// =
c1 = c3;
//
// , 5.2 , , c1
c2 = 5.2;
// ( )
Complex c5(c2);
Complex c4 = c2; // = , , , c2
}</span>
三、思考とテスト
1.複製構造関数を注意深く観察する
Complex(const Complex & c)
{
// c
m_real = c.m_real;
m_img = c.m_img;
}
なぜ関数でオブジェクトcのプライベートメンバーに直接アクセスできるのですか?
2.問題に挑戦し、引用と伝達値の違いを理解する
Complex test1(const Complex& c)
{
return c;
}
Complex test2(const Complex c)
{
return c;
}
Complex test3()
{
static Complex c(1.0,5.0);
return c;
}
Complex& test4()
{
static Complex c(1.0,5.0);
return c;
}
void main()
{
Complex a,b;
// , ?
test1(a);
test2(a);
b = test3();
b = test4();
test2(1.2);
// ?
test1(1.2); //test1( Complex(1.2 )) ?
}
四、付録(浅いコピーと深いコピー)
前述したように、カスタムレプリケーションコンストラクション関数がない場合、デフォルトのレプリケーションコンストラクション関数が作成されますが、システムが作成したデフォルトのレプリケーションコンストラクション関数は、コピーされたオブジェクトのデータ・メンバーの値を新規作成されたペアに割り当てる「浅いコピー」のみを実行します.このクラスのデータ・メンバーにポインタ・メンバーがある場合、新しいオブジェクトのポインタが指すアドレスがコピーされたオブジェクトのポインタが指すアドレスと同じになり、deleteポインタをdeleteするとdeleteが2回繰り返されてエラーが発生します.次に例を示します.
【浅いコピーと深いコピー】
<span style="font-size:18px;">#include <iostream.h>
#include <string.h>
class Person
{
public :
//
Person(char * pN)
{
cout << " !
";
m_pName = new char[strlen(pN) + 1];
// pN
if(m_pName != NULL)
{
// m_pName , pN
strcpy(m_pName ,pN);
}
}
// ,
Person(Person & p)
{
//
m_pName = p.m_pName;
}
~Person( )
{
delete m_pName;
}
private :
char * m_pName;
};
void main( )
{
Person man("lujun");
Person woman(man);
// man woman
//
// delete
}
// , “ ”, ,
Person(Person & chs);
{
// new
m_pName=new char[strlen(p.m_pName)+ 1];
if(m_pName)
{
//
strcpy(m_pName ,chs.m_pName);
}
// m_pName chs m_pName
}</span>