記事のディレクトリ
1つは、コンストラクターです
プログラム実行の過程で、ステートメントステートメントに遭遇すると、プログラムは、新しく作成されたオブジェクトを格納するための一定量のメモリスペースをオペレーティングシステムに適用します。しかし、通常の変数と比較すると、クラスのオブジェクトは特に複雑であり、コンパイラーはオブジェクトを初期化するコードを生成する方法を知らないため、コンストラクターにつながります。
1.1コンストラクターとは何ですか?
C ++では、コンストラクターは特別なメンバー関数であり、コンパイラーは、クラスが作成されるたびに、初期化のためにデフォルトでコンストラクターを呼び出します。
1.2コンストラクターがあるのはなぜですか?
コンストラクターの役割は、オブジェクトの作成時に特定の値でオブジェクトを構築し、オブジェクトを特定の状態に初期化することです。
1.3コンストラクターの使い方は?
コンストラクターの使用方法を学ぶには、最初にコンストラクターのいくつかの特別なプロパティを理解する必要があります。コンストラクターの関数名はクラス名と同じであり、戻り値はありません。コンストラクターは通常、パブリック関数として宣言されます。 。
注:クラスにコンストラクターがある限り、コンパイラーは、新しいオブジェクトが作成される場所にコンストラクターを呼び出すコードを自動的に挿入します。したがって、オブジェクトが作成されると、コンストラクターが自動的に呼び出されます。
以下に、いくつかの一般的なコンストラクターを紹介します。
- デフォルトのコンストラクター:
class Clock
{
public:
Clock() //编译器自动生成的隐含的默认构造函数;
{
}
....
};
デフォルトのコンストラクターが呼び出されるときにパラメーターを指定する必要はありません。コンストラクターがクラスに記述されていない場合、コンパイラーは暗黙のデフォルトコンストラクターパラメーターを自動的に生成します。コンストラクターのパラメーターリストと関数本体は空であり、コンストラクターは何もしません。
注:パラメーターなしのコンストラクターと完全なデフォルトのコンストラクターはどちらもデフォルトのコンストラクターと呼ばれます。
Q:デフォルトのコンストラクターは何もしないのに、なぜこのコンストラクターを生成したいのですか?
回答:オブジェクトの作成時にコンストラクターが自動的に呼び出されると、C ++は何かを実行する必要があるためです。上記の例では、デフォルトのコンストラクターは何もしませんが、関数本体が空のコンストラクターの中には、基本クラスの構築とメンバーオブジェクトの構築も担当するため、何もしないものがあります。
- パラメーターコンストラクターとパラメーターレスコンストラクター
class Clock
{
public:
Clock(int NewH,int NewM,int NewS); //有参数的构造函数
Clock() //无参数的构造函数
{
hour = 0;
minute = 0;
second = 0;
}
void SetTime(int NewH,int NewM,int NewS);
void ShowTime();
private:
int hour,minute,second;
};
int main()
{
Clock(0,0,0); //调用有参数的构造函数
Clock my_clock; //调用无参数的构造函数
return 0;
}
上記の例では、オーバーロードされたコンストラクターには、パラメーター化されたコンストラクターとパラメーター化されていないコンストラクター(つまり、デフォルトのコンストラクター)の2つの形式があります。
1.4コンストラクターの実現
Clock::Clock(int NewH, int NewM, int NewS)
{
hour = NewH;
minute = NewM;
second = NewS;
}
第二に、コピーコンストラクター
オブジェクトのコピーを作成する方法は2つあります。最初の方法は、新しいオブジェクトを作成してから、元のオブジェクトのデータメンバーを取り出して、それを新しいオブジェクトに割り当てることです。これは明らかに面倒なので、クラスにこのクラスのオブジェクトを単独でコピーする機能を持たせるために、コピーコンストラクターが導入されています。
2.1コピーコンストラクタとは何ですか?
コピーコンストラクターは特別なコンストラクターであり、一般的なコンストラクターのすべての特性を備えており、その仮パラメーターはこのクラスのオブジェクトへの参照です。
2.2コピーコンストラクターがあるのはなぜですか?
コピーコンストラクターの役割は、既存のオブジェクト(コピーコンストラクターのパラメーターで指定)を作成して、同じ種類の新しいオブジェクトを初期化することです。プログラムがクラスのコピーコンストラクターを定義していない場合、システムは必要に応じて非表示のコピーコンストラクターを自動的に生成します。この隠しコピーコンストラクターの機能は、初期値オブジェクトの各データメンバーを新しく作成されたオブジェクトにコピーすることです。このようにして得られたオブジェクトは、元のオブジェクトと同じデータメンバーと属性を持っています。
2.3コピーコンストラクターの機能
コピーコンストラクターの機能を説明する前に、コピーコンストラクターを宣言して実装する一般的な方法を見てみましょう。
class 类名
{
public:
类名(形参); //构造函数
类名(类名& 对象名); //复制构造函数
...
};
类名::类名(类名 &对象名) //复制构造函数的实现
{
//函数体
}
前に知っているように、通常のコンストラクターはオブジェクトの作成時に呼び出され、コピーコンストラクターは次の3つの状況で呼び出されます。
例:
class Point
{
public:
Point(int x = 0,int y = 0)
{
_x = x;
_y = y;
}
Point(Point& p); //复制构造函数
int GetX()
{
return _x;
}
int GetY()
{
return _y;
}
private:
int _x,_y;
};
- クラスのオブジェクトを使用して別のオブジェクトを初期化する場合:
int main()
{
Point a(1,2);
Point b(a); //用对象a初始化对象b时,复制构造函数被调用
Point c = a; //用对象a初始化对象c时,复制构造函数被调用
return 0;
}
注:上記のbとcの初期化では、コピーコンストラクターを呼び出すことができます。2つの書き込みメソッドは同等であり、実行される操作はまったく同じです。
- 関数の仮パラメーターがクラスのオブジェクトである場合、関数が呼び出されると、仮パラメーターと実際のパラメーターが組み合わされます。
void Fun(Point p)
{
//函数体
}
int main()
{
Point a(1,2);
Fun(a); //函数的形参为类的对象,当调用对象时,复制构造函数被调用.
return 0;
}
注:オブジェクトが値で渡された場合にのみ、コピーコンストラクターが呼び出されます。パスが参照の場合、コピーコンストラクターは呼び出されません。したがって、これは、参照による受け渡しが値による受け渡しよりも効率的である理由でもあります。
- 関数の戻り値がクラスのオブジェクトである場合、関数が完了して呼び出し元に戻ると、次のようになります。
Point Fun()
{
Point a(1,2);
return a; //函数Fun的返回值是类的对象,返回函数值的时候,调用复制构造函数
}
int main()
{
Point b;
b = Fun();
return 0;
}
Q:この場合、関数値が返されるときにコピーコンストラクターが呼び出されるのはなぜですか?
回答:関数Fun()はaをメイン関数に返しますが、aがFun()のローカル変数であることは誰もが知っています。Fun()関数のライフサイクルが終了すると、aは消滅し、戻ることはできません。メイン機能へ。機能後も存続し続けます。したがって、この場合、コンパイラはmain関数に名前のない一時オブジェクトを作成します。一時オブジェクトのライフサイクルはb = Fun()のみです。ステートメントreturnaが実行されると、実際にはコピーコンストラクターが呼び出され、aの値が名前のない一時オブジェクトにコピーされます。関数Fun()が終了すると、オブジェクトaは消えますが、一時オブジェクトはb = Fun()に存在します。この式が計算されると、一時オブジェクトはその作業を完了します。
三、デストラクタ
ローカル変数が関数のライフサイクルで終了すると、関数内のオブジェクトが消えるので、オブジェクトが消えると(オブジェクトを作成するときなど、mallocを使用して関数に動的に適用する)スペース)誰がこれらのいわゆる「アフターケア」作業を行いますか?このようにして、デストラクタにつながります。
デストラクタとは何ですか?
コンストラクタと同様に、デストラクタは通常、クラスのパブリックメンバー関数であり、その名前はクラス名の前の「〜」で構成され、戻り値はありません。デストラクタとコンストラクタの違いは、デストラクタがパラメータを受け入れないことです。(パラメーターは仮想関数にすることができます。)デストラクタを自分で定義しない場合、コンパイラーは、関数本体が空の非表示のデストラクタも自動的に生成します。
デストラクタの宣言を見てみましょう。
class Clock
{
public:
Clock(int NewH,int NewM,int NewS); //有参数的构造函数
Clock() //无参数的构造函数
{
hour = 0;
minute = 0;
second = 0;
}
void SetTime(int NewH,int NewM,int NewS);
void ShowTime();
~Clock(); //析构函数
private:
int hour,minute,second;
};
注:関数本体が空のデストラクタは何もしません。
ヒント:
クラスの構築順序はステートメントの順序で構築されます。
クラスのデストラクタ呼び出しは、コンストラクタ呼び出しの逆の順序で呼び出され
ます。1。グローバルオブジェクトはローカルオブジェクトの前に構築されます
。2。静的オブジェクトは前に構築されます。普通の物。