1.コンストラクタとデストラクタの概要
そのようなクラスがあるとしましょう
#include <string>
class Stock // class declaration
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() {
total_val = shares * share_val; }
public:
void acquire(const std::string & co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
}; // note semicolon at the end
C ++の目標の1つは、標準型を使用するのと同じようにクラスオブジェクトを使用することです。ただし、これまで、この章で提供されるコードでは、
intやstructureなどのStockオブジェクトを初期化できません。
つまり、通常の初期化構文は、Stock型には適用されません。
int year = 2001; // valid initialization
struct thing {
char *pn;
int m:
};
thing amabob = {
"wodge", -23}; // valid initialization
Stock hot = {
"sukie's Autos, Inc ", 200, 50.25 }; //NO! compile error
上記のようにStockオブジェクトを初期化できないのは、データ部分のアクセス状態がプライベートであるため、プログラムがデータメンバーに直接アクセスできないためです。これまで見てきたように、プログラムはメンバー関数を介してのみデータメンバーにアクセスできるため、オブジェクトを正常に初期化するには、適切なメンバー関数を設計する必要があります(データメンバーをプライベートではなくパブリックにすると、今説明したように初期化できます。クラスオブジェクト、ただし、データを公開することは、クラスの主な本来の意図の1つであるデータの非表示に違反します。
一般的に、オブジェクトの作成時にオブジェクトを初期化するのが最善です。たとえば、次のコードについて考えてみます。
Stock gift;
gift.buy(10, 24.75);
Stockクラスの現在の実装に関する限り、ギフトオブジェクトの会社メンバーには価値がありません。クラスの設計では、ユーザーが他のメンバー関数を呼び出す前にacquire()を呼び出すことを前提としていますが、この前提を課すことはできません。
この問題を回避する1つの方法は、オブジェクトの作成時にオブジェクトを自動的に初期化することです。
この目的のために、C ++は、新しいオブジェクトを構築し、それらのデータメンバーに値を割り当てるために特に使用されるコンストラクターの一種である特別なメンバー関数を提供します。より正確には、C ++はこれらのメンバー関数の名前と使用法の構文を提供し、プログラマーは
メソッド定義を提供する必要があります。
名前はクラス名と同じです。たとえば、Stockクラスの可能なコンストラクターの1つは、Stock()という名前のメンバー関数です。コンストラクターのプロトタイプと関数ヘッダーには興味深い機能があります。戻り値はありませんが、void型として宣言されていません。実際、コンストラクターは
型を宣言しません。
1.コンストラクターを宣言して定義します
次に、Stockコンストラクターを作成する必要があります。
Stockオブジェクトに3つの値を指定する必要があるため、コンストラクターに3つのパラメーターを指定する必要があります(4番目の値であるtotal_valメンバーは、sharesとshare_valに基づいて計算されるため、この値をコンストラクター。)
プログラマーは、会社のメンバーを設定し、他の値を0に設定したい場合があります:これは、デフォルトのパラメーターを使用して行うことができます(第8章を参照)。
したがって、プロトタイプは次のようになります。
// constructor prototype with some default arguments
Stock(const string &co, long n=0, double pr =0.0);
最初のパラメーターは、メンバー会社を初期化するために使用される文字列へのポインターです.nパラメーターとpパラメーターは、sharesおよびshare_valメンバーの値を提供します。戻り値の型がないことに注意してください。プロトタイプは、クラス宣言の公開部分にあります。
コンストラクターの可能な定義は次のとおりです
Stock::Stock(const string & co, long n, double pr)
{
company = co;
if (n < 0) {
std::cerr <<"Number of shares can't be negative;"
<< company << "shares set to 0. \n";
shares =0;
} else {
shares = n;
}
share_val = pr;
set_tot();
}
上記のコードは、この章で前述したacquire()関数と同じです。
違いは、プログラムがオブジェクトを宣言すると、コンストラクターが自動的に呼び出されることです。
2.コンストラクターを使用します
C ++には、コンストラクターを使用してオブジェクトを初期化する2つの方法があります。
最初の方法は、コンストラクターを明示的に呼び出すことです。
Stock food = Stock("World Cabbage", 250, 1.25);
これにより、foodオブジェクトのcompanyメンバーが文字列 "World Cabbage '"に設定され、sharesメンバーが250に設定されます。
別の方法は、コンストラクターを暗黙的に呼び出すことです。
Stock garment("Furry Mason", 50, 2.5);
この形式はよりコンパクトで、次の明示的な呼び出しと同等です
Stock garment = Stock("Furry Mason", 50, 2.5);
クラスオブジェクトを作成するたびに(newを使用して動的にメモリを割り当てる場合でも)、C ++はクラスコンストラクタを使用します。newでコンストラクターを使用する方法は次のとおりです。
Stock *pstock= new Stock("Electroshock Games", 18, 19.0);
このステートメントは、Stockオブジェクトを作成し、パラメーターで指定された値に初期化し、オブジェクトのアドレスをstockポインターに割り当てます。この場合、オブジェクトには名前がありませんが、ポインターを使用してオブジェクトを管理できます。オブジェクトポインタについては、第11章で詳しく説明します。
コンストラクターの使用方法は、他のクラスメソッドとは異なります。一般に、オブジェクトを使用してメソッドを呼び出します。
stock1.show(); //stock1 object invokes show() method
ただし、コンストラクターがオブジェクトを作成する前にオブジェクトが存在しないため、オブジェクトを使用してコンストラクターを呼び出すことはできません。したがって、コンストラクターはオブジェクトの作成に使用され、オブジェクトを介して呼び出すことはできません。
コンストラクターは特別なクラスメンバー関数であり、クラスオブジェクトの作成時に呼び出されます。
コンストラクターの名前はクラス名と同じですが、関数のオーバーロードにより、各関数のシグネチャ(パラメーターリスト)が異なる場合は、同じ名前の複数のコンストラクターを作成できます。さらに、コンストラクターは型を宣言しません。
通常、コンストラクターはクラスオブジェクトのメンバーを初期化するために使用され、初期化はコンストラクターのパラメーターリストと一致する必要があります。たとえば、Bozoクラスのコンストラクターのプロトタイプが次のようになっているとします。
Bozo(const char * fname,const char * lname); // constructor prototype
これを使用して新しいオブジェクトを初期化できます。
Bozo bozetta = bozo("Bozetta","Biggens"); // primary form
Bozo fufu("Fufu","O'Dweeb"); // short form
Bozo *pc = new Bozo("Popo","Le Peu"); // dynamic object
コンパイラーがC ++ 11をサポートしている場合は、リストの初期化を使用できます。
Bozo bozetta = {
"Bozetta","Biggens"}; //C++11
Bozo fufu("Fufu","O'Dweeb") // C++11;
Bozo *pc = new Bozo{
"Popo","Le Peu"); //C++11
コンストラクターにパラメーターが1つしかない場合、オブジェクトがパラメーターと同じタイプの値に初期化されるときにコンストラクターが呼び出されます。たとえば、そのようなコンストラクタプロトタイプ
bozo(int i)
があるとします。次のいずれかの形式を使用して、オブジェクトを初期化できます。
Bozo dribble =bozo(44) // primary form
Bozo roon(66); // secondary form
Bozo tubby = 32; // special form for one-argument constructors
実際、3番目の例は新しいコンテンツであり、レビューコンテンツではありませんが、今がそれを紹介する良い機会です。第11章では、不快な驚きをもたらす可能性があるため、この機能をオフにする方法を紹介します。
警告:パラメーターを受け入れるコンストラクターでは、割り当て構文を使用してオブジェクトを値に初期化
Classname object = value;
できます。この機能は問題を引き起こす可能性がありますが、第11章で紹介するように、この機能をオフにすることができます。
3.1つのパラメーターを受け入れるコンストラクターの例
コンストラクター.cpp
#include <iostream>
/*
author:梦悦foundation
公众号:梦悦foundation
可以在公众号获得源码和详细的图文笔记
*/
using std::cout;
using std::endl;
class Bozo {
public:
int iVar;
Bozo(int i) {
cout << "i = " << i << endl;
this->iVar = i;
}
void show();
};
void Bozo::show()
{
cout << "iVar = " << this->iVar <<endl;
}
int main()
{
cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
Bozo dribble = Bozo(44); // primary form
Bozo roon(66); // secondary form
Bozo tubby = 32; // special form for one-argument constructors
dribble.show();
roon.show();
tubby.show();
cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
}
演算結果:
meng-yue@ubuntu:~/MengYue/c++/object_class/02$ ./constructor
---------------开始--->公众号:梦悦foundation---------------
i = 44
i = 66
i = 32
iVar = 44
iVar = 66
iVar = 32
---------------结束--->公众号:梦悦foundation---------------
meng-yue@ubuntu:~/MengYue/c++/object_class/02$
ご覧のとおり、クラスインスタンスに整数を直接割り当てることもできます。
デフォルトのコンストラクターにはパラメーターがないため、オブジェクトの作成時にオブジェクトが明示的に初期化されていない場合は、デフォルトのコンストラクターが呼び出されます。
プログラムにコンストラクターが指定されていない場合、コンパイラーはプログラムのデフォルトコンストラクターを定義します。それ以外の場合は、デフォルトのコンストラクターを自分で指定する必要があります。
初期化されていないオブジェクトの場合、プログラムはデフォルトのコンストラクターを使用して以下を作成します。
Bozo bubi;// use default
Bozo *pb = new Bozo; // use default
オブジェクトの作成時にプログラムがコンストラクタを呼び出すのと同様に、オブジェクトが削除されるとプログラムはデストラクタを呼び出します。
各クラスは1つのデストラクタのみを持つことができます。デストラクタには戻り値の型(voidでさえも)もパラメータもありません。その名前の前にはクラス名が付いてい~
ます。たとえば、Bozoクラスのデストラクタのプロトタイプは次のとおりです。
// class destructor
~Bozo();
コンストラクタがnewを使用する場合は、deleteを使用してデストラクタを提供する必要があります。