前回の記事の最後で、このポインタについて説明しました。今回は、空のクラスから始めて、この記事のすべてのコンテンツが空のクラスを中心に展開します。…
序章:
1.クラスの6つのデフォルトメンバー関数
2.コンストラクター
3.デストラクタ
4.コンストラクターをコピーします
5.演算子のオーバーロード
6.constメンバー関数
7.アドレスおよび定数アドレス演算子のオーバーロード
コンテンツ
5.パラメーターを値でコピーコンストラクターに渡すときに、なぜ無限の再帰呼び出しが発生するのですか?
6.コンパイラーによって生成されたデフォルトのコピーコンストラクターはすでにバイトオーダー値のコピーを完了できるので、それを自分で実装する必要がありますか?
2. constオブジェクトは非constメンバー関数を呼び出すことができますか?
3.非constオブジェクトはconstメンバー関数を呼び出すことができますか?
4. constメンバー関数内で他の非constメンバー関数を呼び出すことはできますか?
5.他のconstメンバー関数は、非constメンバー関数内から呼び出すことができますか?
7.アドレス演算子のオーバーロードとconstアドレス演算子のオーバーロード
1.クラスの6つのデフォルトメンバー関数
クラスにメンバーがない場合(略して空のクラスと呼ばれます)、空のクラスには何もありませんか?それは何もありません。記述しない場合、どのクラスも次の6つのデフォルトメンバー関数を自動的に生成します。
では、デフォルトのメンバー関数は何ですか?---->ユーザーがそれを記述しない場合、コンパイラーはそれを自動的に生成しますが、ユーザーが定義を表示すると、コンパイラーはそれを生成しなくなります。
2.コンストラクター
1.コンストラクターとは:
コンストラクターは、クラス名と同じ名前の特別なメンバー関数です。クラスタイプのオブジェクトが作成されると、コンパイラーによって自動的に呼び出され、各データメンバーが適切な初期値を持つようにします。このコンストラクターは、オブジェクトのライフサイクル全体。1回。
2.機能:
オブジェクトを初期化し、オブジェクト内の各データメンバーが適切な初期値を持っていることを確認します。
3.デフォルトのコンストラクター:
コンパイラによって自動的に生成されるデフォルトのコンストラクタは、オブジェクトが初期化されるときにオブジェクトのメンバー変数にランダムな値を割り当てることしかできません。オブジェクトにスペースリソースのスケジューリングがある場合は、コンストラクタを使用する代わりに、自分でコンストラクタを定義する必要があります。デフォルトのコンストラクター関数。
4.機能:
1.関数名はクラス名と同じです。
2.戻り値はありません。
例えば:
class Date{
Date(){
//该函数就是一个默认的构造函数.
}
}
3.オブジェクトがインスタンス化されると、コンパイラーは対応するコンストラクターを自動的に呼び出します。
知らせ:
①。オブジェクトの作成時にパラメーターを渡すと、コンパイラーはパラメーターに従って対応するコンストラクターを呼び出し、オブジェクトを初期化します。
②。オブジェクトを直接作成して何もしない場合、コンパイラは自動的にデフォルトのコンストラクタを呼び出してオブジェクトの初期化を完了します。デフォルトのコンストラクタは何ですか?次の3つがあります。
a。システム自体によって生成されるデフォルトのコンストラクターである定義は表示されません。
b。パラメーターなしのコンストラクターを明示的に定義します。
c。完全なデフォルトコンストラクターを明示的に定義します。
4.コンストラクターはオーバーロードできます
考える:
a。コンストラクターはオーバーロードできるため、独自の要件に従ってオブジェクトを初期化できます。この機能がないと、デフォルトのコンストラクターしか使用できず、プログラミングの効率に影響を与える可能性があります。
知らせ:
a。オブジェクトがパラメーターなしのコンストラクターによって作成される場合、オブジェクトの後に括弧を付ける必要はありません。それ以外の場合は、関数宣言になります。例:Date d3();このコードは、パラメーターを持たないd3関数を宣言します。関数名はd3で、戻り値は日付型です。
例えば:
class Date{
public :
// 1.无参构造函数
Date ()
{}
// 2.带参构造函数
Date (int year, int month , int day ){
_year = year ;
_month = month ;
_day = day ;
}
private :
int _year ;
int _month ;
int _day ;
};
void TestDate(){
Date d1; // 调用无参构造函数
Date d2 (2015, 1, 1); // 调用带参的构造函数
}
5.ユーザーが自分で作成しない場合、コンパイラーはパラメーターなしのデフォルトコンストラクターを自動的に生成しますが、ユーザーが定義を表示すると、コンパイラーはそれを生成しなくなります。
知らせ:
a。ここで説明している明示的な定義は、上記のオーバーロードとは関係ありません。ここでの明示的な定義は、パラメーターなしのデフォルトコンストラクターまたは完全なデフォルトのデフォルトコンストラクターを定義する場合を指しますが、コンパイラーはそれを生成しなくなりますが、オーバーロードの形式でパラメーターを指定する必要があるコンストラクターを明示的に定義すると、このコンストラクターはデフォルトコンストラクターに属しなくなり、コンパイラーはパラメーターなしのデフォルトコンストラクターを自動的に生成します。
6.パラメーターなしコンストラクターとすべてデフォルトコンストラクターはデフォルトコンストラクターと呼ばれ、デフォルトコンストラクター、パラメーターなしコンストラクター、すべてデフォルトコンストラクター、およびコンパイラー生成のデフォルトコンストラクターのみが存在できます。デフォルトは、コンパイラーが呼び出すことを意味します。オブジェクトが作成されるときのデフォルトのコンストラクタ。
考え:コンパイラーによって自動的に生成されるデフォルトのコンストラクターは役に立ちますか?
a。クラスのメンバー変数がすべてシステムタイプであると仮定すると、コンパイラーによって生成されたデフォルトコンストラクターが呼び出された後も、メンバー変数の初期値はランダムであり、現時点ではデフォルトコンストラクターは役に立ちません。
b。クラスのメンバー変数にシステム型変数だけでなく、カスタム型のオブジェクト(メンバー変数にも属する)もあると仮定すると、インスタンス化するときに、内部カスタム型のメンバー変数をどのように実装しますか?クラス初期化の場合、直接初期化することはできません。このとき、コンパイラは、自動生成されたデフォルトコンストラクタを呼び出すときに役割を果たします。コンパイラは、生成されたデフォルトコンストラクタの内部カスタムメンバー変数に対応するデフォルトコンストラクタを呼び出します。完了クラス内のカスタムメンバー変数の初期化。
例えば:
class Time{
public:
Time(){
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date{
private:
// 基本类型(内置类型)
int _year;
int _month;
int _day;
// 自定义类型
Time _t;
};
int main(){
//在创建对象d时我们不能直接完成对_t的初始化,此时Date中编译器自动生成的默认构造函数产生作用
//创建对象d时,会自动调用Date中默认的构造函数,而默认的构造函数会调用_t这个自定义对象的构造函数
//完成对_t的初始化
Date d;
return 0;
}
3.デストラクタ
1.デストラクタとは何ですか?
コンストラクターの機能とは異なり、デストラクタはオブジェクト自体の破棄を完了せず、ローカルオブジェクトの破棄はコンパイラによって完了します。オブジェクトは、破棄されると自動的にデストラクタを呼び出して、のリソースのクリーンアップを完了します。物体。
2.機能:
オブジェクト内のリソースのクリーンアップを完了します(オブジェクト内のリソース--->ヒープ、ファイルポインター、ソケットに適用されるメモリスペース...)
3.デフォルトのデストラクタ:
クラスには1つだけのデストラクタがあります。明示的に定義されていない場合、システムはデフォルトのデストラクタを自動的に生成します。ただし、オブジェクト内のリソースをクリーンアップするには、デストラクタを自分で定義する必要があります。コンパイラのデフォルトは、生成されたデストラクタには、この機能はありません。
4.機能:
1.デストラクタ名の前に文字〜が付きます。
2.パラメータも戻り値もありません。
例えば:
class Date{
~Date(){
//该函数就是一个默认的析构函数.
}
}
3.クラスには1つだけのデストラクタがあります。明示的に定義されていない場合、システムはデフォルトのデストラクタを自動的に生成します。
知らせ:
デストラクタにはオーバーロード特性がありません。クラスにはデストラクタが1つしかありません。明示的に定義すると、コンパイラは自動的に生成しません。オブジェクトに解放する必要のあるスペースリソースがある場合は、デストラクタを自分で定義する必要があります。関数を定義する場合、関数名の前にクラス名の前に〜が付いていることに注意してください。戻り値やパラメーターはなく、リソースを解放する操作を関数本体に配置できます。
4.オブジェクトのライフサイクルの終わりに、C++コンパイルシステムは自動的にデストラクタを呼び出します。
思考:デフォルトで生成されたデストラクタはスペースリソースを解放できません。スペースリソースのないオブジェクトは、破棄されると自然に終了する可能性があり、関連する破棄作業を実行する必要はありません。デフォルトのデストラクタの使用法は何ですか。
a。クラスのメンバー変数にカスタム型がない場合、デフォルトでコンパイラによって生成されたデストラクタは効果がありません。
b。クラスにカスタム型のメンバー変数がある場合、オブジェクトが破棄されたときにこれらの変数を直接解放することはできません。この場合、コンパイラによって生成されたデフォルトのデストラクタは、のカスタム型デストラクタのメンバーでそれを呼び出します。 。
例えば:
class String{
public:
String(const char* str = "jack"){
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String(){
cout << "~String()" << endl;
free(_str);
}
private:
char* _str;
};
class Person{
private:
String _name;//自定义类型
int _age;
};
int main(){
//当我们的对象p生命周期结束时,需要对p对象中的资源进行释放,p对象并没有资源,但是p对象中的自定义
//类型对象_name中有空间资源,我们没法直接对其进行释放,此时p对象中的默认析构函数的作用就体现出
//来了,它会调用自定义类型对象中的析构函数,将该自定义类型对象中的资源释放.
Person p;
return 0;
}
4.コンストラクターをコピーします
1.コピーコンストラクターとは何ですか?
この関数には、このクラスタイプのオブジェクトへの参照であるパラメーターが1つだけあります(通常、変更されないようにconstで変更されます)。これは、既存のオブジェクトで新しいオブジェクトが作成されるときにコンパイラーによって自動的に呼び出されます。クラスタイプオブジェクト。
2.機能:
クラス型オブジェクトを作成するときに、既存のクラス型オブジェクトの値を作成するオブジェクトに浅くコピーできます(ディープを完了したい場合は、コンパイラによって自動的に生成されるデフォルトのコピーコンストラクタは浅いコピーのみを実行できますコピーする必要があります。コピーコンストラクターは自分で定義します。)
3.浅いコピーとは何ですか?
浅いコピーとは、バイトオーダー値のコピーを指します。つまり、同じクラスタイプのオブジェクト内の対応するメンバー変数は、1対1の方法でコピーされます。
4.機能:
1.コピーコンストラクターは、オーバーロードされた形式のコンストラクターです。
定義方法:
Date(const Date& d){
_year = d._year;
_month = d._month;
_day = d._day;
}
2.コピーコンストラクターのパラメーターは1つだけであり、パラメーターは参照によって渡される必要があります。パラメーターが値によって渡される場合、無限の再帰呼び出しが発生します。
3.明示的な定義がない場合、システムはデフォルトのコピーコンストラクターを生成し、デフォルトのコピーコンストラクターオブジェクトはメモリストレージとバイトオーダーに従ってコピーを完了します。このコピーはシャローコピーまたはバリューコピーと呼ばれます。
5.パラメーターを値でコピーコンストラクターに渡すときに、なぜ無限の再帰呼び出しが発生するのですか?
a。まず、通常は参照によってパラメーターを渡すことを知っておく必要があります。パラメーターを値で渡さない理由を見てみましょう。
b。まず、通常の関数を例にとると、パラメーターを値の形式で渡すとどうなりますか。コンパイラーは、関数の実パラメーターをに渡した後、実パラメーターと同じタイプの一時変数を生成します。実際のパラメータの値。コピーしてから、この一時変数を関数で使用します。これは、実際のパラメータとは関係ありません。このとき、パラメータが値の形式で渡されたときに何が起こるかを見てみましょう。コピーコンストラクタ。最初に、関数は渡された実際のパラメータオブジェクトを受け取りますが、これは値を渡すパラメータであるため、この時点で関数は一時オブジェクトを作成し、実際のパラメータオブジェクトの値をこの一時オブジェクトにコピーします。 、では、オブジェクトを作成するときに実際のオブジェクトのコピーを完成させるにはどうすればよいですか?もちろん、実際のパラメーターオブジェクトをパラメーターとして使用して、一時オブジェクトのコピーコンストラクターが呼び出されます。この時点で、に戻ります。パラメーターを渡すためにコンストラクターが呼び出されたとき。このようにすると、再帰呼び出しが続行されるため、コンストラクターをコピーします。パラメーターを渡すときに値渡しを使用することはできません。
。
6.コンパイラーによって生成されたデフォルトのコピーコンストラクターはすでにバイトオーダー値のコピーを完了できるので、それを自分で実装する必要がありますか?
a。クラスでメンバー変数を定義するときに、メンバー変数の型が通常の変数のみである場合は、コピーコンストラクターを自分で定義する必要はありません。
b。メンバー変数の型がポインター型の場合、事故が発生します。コピーコンストラクターを呼び出すと、既存オブジェクトのメンバーポインター変数の内容が、新しく生成されたオブジェクトのポインター変数に完全にコピーされます。 。この時点で、2つのオブジェクトのポインタ変数は同じアドレスに格納されます。つまり、同じメモリスペースを指します。プログラムの最後に、最後のオブジェクトが最初に破棄され、オブジェクトのデストラクタが破棄されます。ポインタが指すスペースが解放され、前のオブジェクトが破棄されると、オブジェクトのデストラクタが呼び出された後、ポインタ変数が指すスペースが再び解放されます。これは、が指すスペースがポインタが解放された後、ポインタ変数もワイルドポインタになり、ポインタが指すスペースが解放されるとプログラムがクラッシュするため、この場合、独自のコピーコンストラクタを定義する必要があります。
7.コピーコンストラクターを使用するシナリオ:
1.既存のオブジェクトを使用して新しいオブジェクトを作成します。
2.関数の仮パラメータ型がクラス型のオブジェクトである場合。
3.関数の戻り値型がクラス型のオブジェクトである場合。
注: したがって、上記のシナリオでは、コピーコンストラクターを呼び出しますが、これはプログラムの効率に大きく影響します。したがって、プログラムの効率を向上させるために、一般的なオブジェクトでパラメーターを渡すときに参照型を使用するようにしてください。 。関数が戻ったとき、実際のシーンに応じて、可能な限り参照を使用できます。
5.代入演算子のオーバーロード
1.なぜ演算子のオーバーロードを使用するのですか?
C ++では、コードの可読性を高めるために演算子のオーバーロードが導入されています。演算子のオーバーロードは、特別な関数名を持つ関数であり、戻り値のタイプ、関数名、およびパラメーターリストもあります。戻り値のタイプとパラメーターリストは類似しています。通常の機能に。
2.関数名と関数プロトタイプ
例えば:
bool operator==(const Date& d1, const Date& d2)//==运算符重载
{
return d1._year == d2._year;
&& d1._month == d2._month
&& d1._day == d2._day;
}
3.注意事項
1.他のシンボル(operator @など)を接続して新しい演算子を作成することはできません。
2.オーバーロードされた演算子には、クラス型または列挙型のオペランドが必要です。
3.組み込み型に使用される演算子の意味は変更できません。たとえば、組み込み整数型+はその意味を変更できません。
4.クラスメンバーのオーバーロードされた関数として、その仮パラメーターはオペランドの数より1少ないように見え、メンバー関数の演算子にはデフォルトパラメーターthisがあり、これは最初のパラメーターに制限されています。
5.オーバーロードできない演算子とオーバーロードできる演算子。
4.代入演算子のオーバーロード
a。代入演算子は、主に次の4つの点に注意します。
1.パラメータタイプ2.戻り値3.自分に値を割り当てているかどうかを確認します4.*thisを返します
b。注:
1.クラスが代入演算子のオーバーロードを明示的に定義していない場合、コンパイラはオブジェクトのエンディアン値のコピー(浅いコピー)を完了するために代入演算子のオーバーロードも生成します。
2.割り当て演算子のオーバーロードは、クラス内でのみ定義できます。クラスの外部でグローバル割り当て演算子のオーバーロードを定義する場合、現時点ではクラス内に割り当て演算子のオーバーロードがないため、コンパイラはデフォルトの割り当て演算子のオーバーロードを生成します。今回は、これがデフォルトの割り当て演算子のオーバーロードとクラス外のグローバル割り当て演算子のオーバーロードと重複しているため、競合するため、割り当て演算子のオーバーロードをクラスに配置する必要があります。
c。コンパイラによって生成されたデフォルトの代入オーバーロード関数は、すでにバイトオーダー値のコピーを完了できますが、それでも自分で実装する必要がありますか?
特定の場合に必要な特定の理由は、コピーコンストラクターと同等です。
6.constメンバー関数
1. constメンバー関数とは何ですか?
a。const-modifiedクラスメンバー関数はconstメンバー関数と呼ばれます。const-modifiedクラスメンバー関数は、実際にはメンバー関数の暗黙のthisポインターを変更します。constは実際にはthisポインターの前に配置され、メンバー関数クラスのメンバーは変更できません。
例えば:
2. constオブジェクトは非constメンバー関数を呼び出すことができますか?
いいえ、constオブジェクトにのみアクセスできます。*constメンバー関数内のこのオブジェクトにはアクセスできません。これらのオブジェクトはアクセス可能で変更可能です。
3.非constオブジェクトはconstメンバー関数を呼び出すことができますか?
はい、非constオブジェクトにアクセスして変更できます。*これはconst関数でのみアクセスできるため、はい。
4. constメンバー関数内で他の非constメンバー関数を呼び出すことはできますか?
いいえ、* const関数のthisはアクセスのみ可能ですが、他の非const関数の*thisはアクセスおよび変更できます。
5.他のconstメンバー関数は、非constメンバー関数内から呼び出すことができますか?
はい、*これは非const関数でアクセスおよび変更できますが、*これはconst関数でのみアクセスできます。
7.アドレス演算子のオーバーロードとconstアドレス演算子のオーバーロード
1.注:
通常、これら2つの演算子はオーバーロードする必要はありません。コンパイラによって生成されたデフォルトのアドレスフェッチのオーバーロードを使用できます。たとえば、他の人に指定されたコンテンツを取得させたい場合など、特別な場合にのみオーバーロードが必要です。
2.アドレスを取得します。
例として日付クラスを取り上げます。
Date* operator&(){
return this ;
}
3.constはアドレスを取得します。
例として日付クラスを取り上げます。
const Date* operator&()const{
return this ;
}