[C++ クラスとオブジェクト] クラスにはどのようなデフォルトのメンバー関数がありますか? (優れた)

目次

1. クラスの 6 つのデフォルトのメンバー関数

2.コンストラクター(*^▽^*)

2.1 コンセプト

2.2 特徴

3. デストラクター(*^▽^*)

3.1 コンセプト

3.2 特徴

4. コンストラクターをコピーします(*^▽^*)

4.1 コンセプト

4.2 特徴

5. 代入演算子のオーバーロード (*^▽^*)

5.1 演算子のオーバーロード

5.2 代入演算子のオーバーロード


ヾ(๑╹◡╹)ノ「人は常に過去の怠惰の代償を払わなければなりません!ヾ(๑╹◡╹)ノ」


1. クラスの 6 つのデフォルトのメンバー関数

クラスにメンバーが存在しない場合、そのクラスは単に空のクラスと呼ばれます。
空のクラスには何もないわけではなく、どのクラスも何も記述していない場合、コンパイラは以下の 6 つのデフォルトのメンバー関数を自動的に生成します。

 デフォルトのメンバー関数: ユーザーによる明示的な実装を行わずにコンパイラによって生成されたメンバー関数は、デフォルトのメンバー関数と呼ばれます。

2.コンストラクター(*^▽^*)

2.1 コンセプト

データクラスの場合:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Init(2022, 7, 5);//初始化
	d1.Print();
	Date d2;
	d2.Init(2022, 7, 6);//初始化
	d2.Print();
	return 0;
}

上記のコードでは、Init public メソッドを通じてオブジェクトの日付を設定し、オブジェクトが作成されるたびにこのメソッドを呼び出して情報を設定できます。

コンストラクターは、 クラス名と同じ名前を持つ特殊なメンバー関数 です 。これは、クラス型オブジェクトの作成時にコンパイラーによって自動的に呼び出され、各データ メンバーが適切な初期値を持つことを保証し、生涯に 1 回だけ呼び出されます。オブジェクトのサイクル

2.2 特徴

コンストラクターは特別なメンバー関数です。コンストラクターの名前はコンストラクターと呼ばれていますが、コンストラクターの主なタスクはオブジェクトを作成するためのスペース を開くことではなく、オブジェクトを初期化することであることに 注意してください
特徴:
1. 関数名はクラス名と同じです。
2. 戻り値はありません。
3. コンパイラは、オブジェクトがインスタンス化されるときに、 対応するコンストラクターを 自動的に呼び出します。
4. コンストラクターはオーバーロードできます。[ただし、私たちが書くもののほとんどはデフォルトのコンストラクターであり、一般に関数のオーバーロードは必要ありません [デフォルトのコンストラクター + 他の関数のオーバーロードを作成します]]
class Date
{
public:
	// 1.无参构造函数
	Date()//构造函数:函数名与类名相同,无返回值
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	// 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 d1();
	Date d2(2015, 1, 1); // 调用带参的构造函数
	// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
}
5. クラスに明示的に定義されたコンストラクターがない場合、 C++コンパイラーは パラメーターなしでデフォルトのコンストラクターを 自動的に生成します。ユーザーがコンパイラーを明示的に定義すると、それは生成されなくなります[つまり、コンストラクターが実装されていない場合、C++ コンパイラーはパラメーターのないデフォルトのコンストラクターを自動的に生成します]

 デフォルトのコンストラクター: (1) 引数のないコンストラクター (2) 完全なデフォルトのコンストラクター (3) C++ コンパイラーによって生成された引数のないコンストラクター [つまり、デフォルトのコンストラクターがない場合は、3 つのうちの 1 つが必要です] 記述されたコンストラクターパラメータなしではなく、すべてがデフォルトでもありません]エラーが報告されます]

6. コンパイラが生成するデフォルトのメンバ関数については、コンストラクタが実装されていない場合、コンパイラがデフォルトのコンストラクタを生成します。しかし、デフォルトのコンストラクターは役に立たないようです? オブジェクトはコンパイラによって生成されたデフォルトのコンストラクターを呼び出しますが、 オブジェクト _year/_month/_dayは依然としてランダムな値です [組み込み型は依然としてランダムな値です] 言い換えれば、コンパイラーによって生成されたデフォルトのコンストラクターはここでは役に立たないということですか?
回答: C++ では 、型を組み込み型 ( 基本型 ) とカスタム型に分類します。組み込み型は、言語によって提供されるデータ型 (int/char... など) であり、カスタム型は、 class/struct/unionを使用して 独自に定義する型です。コンストラクターが実装されていない場合、コンパイラーは、カスタム type のメンバー に対してデフォルトのメンバー関数を呼び出すデフォルトのコンストラクターを生成します。

クラスのメンバーがすべてカスタム型の場合、デフォルトで生成された関数を使用できます。組み込み型関数のメンバーがある場合、またはパラメーターの初期化を表示する必要がある場合は、コンストラクターを自分で実装する必要があります。(初期化するにはパラメータを渡す必要があり、コンストラクターを自分で実装する必要があります) [ほとんどの場合、コンストラクターを自分で作成します]

C++ コンパイラによって生成されるデフォルト コンストラクターは、組み込み型関数のメンバー変数を処理せずカスタム型メンバーは独自のデフォルト コンストラクターを呼び出します。

注: C++11 では、組み込み型のメンバーが初期化されない、つまり、 クラスで宣言されたときに組み込み型のメンバー変数に デフォルト値が与えられる という欠陥に対してパッチが適用されました。[注: これは宣言であるため、初期化ではなくデフォルト値です]
7. パラメータなしのコンストラクタとデフォルト コンストラクタは両方ともデフォルト コンストラクタと呼ばれ、デフォルト コンストラクタは 1 つだけ存在できます。
注: 引数のないコンストラクター、完全なデフォルト コンストラクター、およびデフォルトでコンパイラーによって生成されるように記述されていないコンストラクターはすべて、デフォルト コンストラクターと見なすことができます。
class Date
{
public:
	Date()//无参的构造函数
	{
		_year = 1900;
		_month = 1;
		_day = 1;
	}
	Date(int year = 1900, int month = 1, int day = 1)//全缺省的构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1;//这里会发生错误,默认构造函数只能有一个
}

実行時にエラーが発生し、競合が発生します。

一般に、C++ クラスは独自のコンストラクターを作成する必要があります。コンパイラーに自動的に生成させることができるのは、まれなケースだけです。

(1) クラス内のメンバーはすべて自己定義型のメンバーであり、これらのメンバーはデフォルトのコンストラクターを提供します。

(2) 組み込み型メンバの宣言時にデフォルト値が与えられます。

3. デストラクター(*^▽^*)

3.1 コンセプト

デストラクター: コンストラクターの機能とは異なり、デストラクターはオブジェクトの破棄を完了しません。ローカル オブジェクトの破棄はコンパイラーによって行われます。 オブジェクトが破棄される と、自動的にデストラクターが呼び出され、クラスの リソース クリーニング作業が完了します。 【破壊】

3.2 特徴

デストラクターは 特別なメンバー関数です。
特徴:
1.デストラクター名は、クラス名の前にある文字 ~ です
2.パラメータも戻り値もありません。
3.クラスにはデストラクターが 1 つだけあります。明示的に定義されていない場合、システムはデフォルトのデストラクターを自動的に生成します [カスタム型の変数は独自のデストラクターを呼び出し、組み込み型の変数は処理されません]。 注: デストラクターは オーバーロード
4.オブジェクトのライフサイクルが終了すると、C++ コンパイル システムが自動的にデストラクターを呼び出します。
5.  コンパイラが自動生成するデストラクタについて、 コンパイラが生成するデフォルトのデストラクタは、カスタム型メンバに対して独自のデストラクタを呼び出します。
6. クラス内にリソース アプリケーションが存在しない場合、デストラクタを記述することはできず、Date クラスなど、コンパイラによって生成されたデフォルトのデストラクタが直接使用されます。リソース アプリケーションがある場合はそれを記述する必要があり、リソース アプリケーションがない場合は、デストラクタを記述する必要が あり ます Stackクラス などのリソース リークが発生します [つまり、リソース アプリケーションがある場合はデストラクターを記述する必要があります]。

4. コンストラクターをコピーします(*^▽^*)

4.1 コンセプト

 オブジェクトが作成されると、オブジェクトとまったく同じ新しいオブジェクトが作成されます。

コピー コンストラクター : このクラス型のオブジェクトへの参照である 仮パラメーターは 1 つだけあり (通常はconst装飾が一般的に使用されます)既存のクラス型オブジェクトを使用して新しいオブジェクトを作成するときにコンパイラーによって自動的に呼び出されます。

4.2 特徴

1.コピー コンストラクターは、コンストラクターのオーバーロード形式です

2.コピー コンストラクターにはパラメーターが 1 つだけあり 参照によって渡す必要があります 値によって渡す方法では、無限の再帰呼び出しが発生します
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)//拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

値を渡す方法: コピー コンストラクターを呼び出すと、コピー コンストラクターが呼び出されます。この関数を呼び出すには、最初にパラメーターを渡す必要があります。パラメーターを渡すことは、一時コピーです。このとき、状態は一時コピー オブジェクトであり、これは次と同等です。コピー構築で、コピー構築関数を呼び出す必要がある場合、この時点で無限再帰呼び出しがトリガーされます。

パラメーターを参照によって渡す: コピー構築は呼び出されません。

[オブジェクトはこのクラスの別のオブジェクトを初期化します。これはコピー構築です] [オブジェクトのコピーはコピー構築です]

カスタム タイプのオブジェクトの場合、コピーの初期化は、コピー コンストラクターを呼び出して完了する必要があります。

定義が表示されない場合、システムはデフォルトのコピー コンストラクターを生成します。 デフォルトのコピー コンストラクター オブジェクトは、メモリ ストレージに従ってバイト オーダーでコピーされます。この種のコピーは、浅いコピー、または値のコピーと呼ばれます。[つまり、組み込み型のメンバーは値のコピー (浅いコピー) を完成し、カスタム型のメンバーはこのメンバーのコピー構築を呼び出します]
結論: 一般的なクラスの場合、自己生成されたコピー構造で十分であり、コピー構造を自分で記述する必要はありません。ただし、スタックのようなリソースを自分で直接管理するクラスの場合は、ディープ コピーを自分で実装する必要があります。
4. コンパイラによって生成されたデフォルトのコピー コンストラクターは、すでにバイト オーダーの値のコピーを完了できますが それでも自分で実装する必要がありますか? もちろん Date クラスのようなクラスは不要です。スタックのようなクラスは許可されません。[スタックにアドレスがある場合、2つのスタックは同じ空間に移動し、追加、削除、確認、変更の際に相互に影響を及ぼします。破壊する場合は、同じ空間を2回破壊し、同じ空間を破壊します。プログラムは崩壊する―結末解決、自分でコピー構築を実現―ディープコピー】
クラスにリソース アプリケーションが関与していない場合は、コピー コンストラクターを記述してもしなくても構いません。リソース アプリケーションが関与すると、コピー コンストラクターを記述する必要があります。それ以外の場合は、コピー コンストラクターは浅いコピーになります。

 プログラムの効率を高めるため、一般オブジェクトにパラメータを渡す場合は、できるだけ参照型を使用し、返すときも現場に合わせて可能な限り参照を使用するようにしてください。

5. 代入演算子のオーバーロード(*^▽^*)

5.1 演算子のオーバーロード

C++ では、 コードの可読性を高める ために 演算子のオーバーロードが導入されています演算子のオーバーロードは、特殊な関数名を持つ関数であり、戻り値の型、関数名、およびパラメーター リストも持っています。戻り値の型とパラメーター リストは、通常の関数と似ています。 。
関数名は 、キーワード 演算子 の後に、オーバーロードする必要がある演算子記号が続きます
関数プロトタイプ 戻り値型  演算子演算子 パラメータ リスト
戻り値: 演算結果
パラメータ: 演算オペランド
知らせ:
(1) 他の記号を結合して新しい演算子を作成することはできません。たとえば、 operator@などです。
(2) オーバーロードされた演算子にはクラス型パラメータが必要です
(3) 組み込み型に使用される演算子の意味は変更できません。たとえば、組み込み整数 + の意味は変更できません。
(4) クラスのメンバー関数としてオーバーロードされた場合、メンバー関数の最初のパラメーターは非表示のこのパラメーターであるため、その仮パラメーターはオペランドの数より 1少ないように見えます。
(5) .*     :: sizeof ?: .上記5 つの演算子はオーバーロードできないことに注意してください。これは筆記試験でもよく出題されます。             
//日期的判断是否相等
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year 
		&& d1._month == d2._month 
		&& d1._day == d2._day;
 }
//放到类里面 Date,此时是在类外面的写法
//1.
if (operator==(d1, d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成1.

(1) 組み込み型はさまざまな演算子を直接使用できますが、カスタム型はさまざまなアルゴリズムを直接使用できません。カスタム型でさまざまな演算子を使用できるようにするために、演算子のオーバーロードがあります。

(2) 関数パラメータはオペランドと同数あります。(== 2 つのオペランド; ++ 1 つのオペランド;)

クラスで書きました:

//日期的判断是否相等
bool operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
//放到类里面 Date,此时是在类里面的写法
//1.
if (d1.operator==(d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成对应重载运算法调用

両方のコードが存在する場合 (関数のオーバーロードに準拠しているため、コンパイラーはパスできます)、コンパイラーはクラス内の演算子のオーバーロードを最初に使用します。

//判断日期小
bool operator<(const Date& d)
{
	//小的情况
	if (_year < d._year
		|| (_year == d._year && _month < d._month)
		|| (_year == d._year && _month == d._month && _day < d._day))
	{
		return true;
	}
	else
	{
		return false;
	}
}

ここでは細部にまで注意を払います。当然のことと思われないでください。

5.2 代入演算子のオーバーロード

1. パラメータの種類
2. 戻り値
3. 自分自身に値を割り当てているかどうかを確認します
4. *こちらを 返却
5. クラスが代入演算子のオーバーロードを明示的に定義していない場合、コンパイラはオブジェクトのバイト順の値のコピーを完成させるために代入演算子のオーバーロードも生成します。
1. 代入演算子のオーバーロード形式
パラメータの型 : const T& 、参照渡しによりパラメータの受け渡しの効率が向上します。
戻り値の型 : T& 、戻り参照により戻りの効率が向上します。戻り値の目的は、継続的な代入をサポートすることです。
自分自身に値を割り当てているかどうかを確認してください
*this を返す : 連続代入の意味を複合化する
//d2 = d1;-> d2.operator(&d2, d1)
Date& operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
int main()
{

	Date d1(2000, 8, 20);
	Date d2(2000, 9, 17);
	Date d3(d1);//拷贝构造,一个存在的对象去初始化另一个要创建的对象
	d2 = d1;//赋值重载(复制拷贝) 两个已经存在的对象之间赋值
}
2. 代入演算子はクラスのメンバー関数としてのみオーバーロードでき、グローバル関数としてオーバーロードできません。
代入演算子はグローバル関数にオーバーロードされます。グローバル関数にオーバーロードする場合、this ポインターがないことに注意してください。2 つのパラメーターが必要ですが、
代入演算子が明示的に実装されていない場合、コンパイラはデフォルトの代入演算子を生成します。このとき、ユーザーはグローバルを実装します。
代入演算子のオーバーロードは、クラスのコンパイラによって生成されるデフォルトの代入演算子のオーバーロードと競合するため、代入演算子のオーバーロードはクラスのメンバー関数のみにすることができます
3. ユーザーが明示的に実装しない場合、コンパイラはデフォルトの代入演算子のオーバーロードを生成します。これは、 value の形式でバイトごとにコピーされます 注: 組み込み型のメンバー変数は直接割り当てられますが、カスタム型のメンバー変数は、割り当てを完了するために対応するクラスの代入演算子オーバーロードを呼び出す必要があります。
4. コンパイラによって生成されるデフォルトの代入オーバーロード関数はすでに byte order の値をコピーできますが 、それでも自分で実装する必要がありますか? もちろん Date クラスのようなクラスは不要です。リソース管理がクラスに関与していない場合、代入演算子が実装されているかどうかは問題ではありませんが、リソース管理が関与している場合は、代入演算子を実装する必要があります。

補足:ヌルポインタは存在しないのでしょうか?が存在し、空のアドレスは既存のアドレスです。

おすすめ

転載: blog.csdn.net/m0_57388581/article/details/132179408