C++ の初級クラスとオブジェクト (パート 2)

はじめに: C++ ビギナー シリーズの各号では、ブロガーはシンプルで平易な言葉を使用して、対応する知識を全員と共有し、誰にでも理解されるように努めます。C++ ビギナー シリーズは引き続き更新され、随時更新されます。学年中には時間がありますが、それ以上の時間は常にあります

目次

1. コンストラクター

1.1 コンストラクターはなぜ存在するのですか?

1.2 コンストラクタの特徴

1.3 コンストラクターの使用 

1.4 ビルトインタイプとカスタムタイプの構造詳細

2. デストラクター

1. デストラクタが存在するのはなぜですか?

2. デストラクタの特徴

3. デストラクターを使用する

3. 次号の予告


1. コンストラクター

1.1 コンストラクターはなぜ存在するのですか?

C言語の学習では、構造体変数を作成したら、まずその構造体変数の初期化を行うのですが、そのための初期化関数を「Init+初期化する構造体の名前」という形で書くことが多いです。シーケンステーブルを例に挙げると、シーケンステーブルを初期化する際にはInitSeqlistなどの関数を書きます。しかし、それを書いたときに、時々それを使うのを忘れてしまいます。はは、それは間違いですか? しかし、これは私たちがよく犯す間違いであり、それが原因でプログラムが期待と矛盾することがよくあります。たとえば、初期化シーケンス テーブルにいます。シーケンス テーブルの最初の要素のポインタを空またはオープン スペースに設定する必要がある場合がありますが、空に設定するのを忘れたり、スペースをオープンするのを忘れたりすると、ワイルド ポインタにアクセスすることになり、予測できない結果が発生します。

そこでC++にはコンストラクターという超便利なものが誕生しました その機能も非常にシンプルで粗雑なものです つまり、対応するクラス(構造体)を作成すると、コンパイラがそれに合わせて書いてくれるのです コンストラクターはコンストラクターを初期化しますあなたが作成するクラス。お母さんはもう私がクラスの初期化を忘れることを心配する必要はありません~

1.2 コンストラクタの特徴

1. 戻り値はありません。
2. 関数名はクラス名と同じです。
3. コンパイラは、オブジェクトがインスタンス化されるときに、対応するコンストラクターを自動的に呼び出します。
4. コンストラクターはオーバーロードできます。

まず最初の点、戻り値なしについて説明します。ここでの戻り値なしには void も含まれます。つまり、void さえ必要なく、コンストラクター名を直接記述するだけです。この時点で 2 番目の点に触れます。 、関数名とクラス名は同じです。たとえば、日付に関するクラスを作成する場合、このクラスに Date という名前を付けると、コンストラクターもクラスとして記述する必要があります。

3 番目の点は、以前に強調した点なので、ここでは繰り返しません。 4 番目のポイントはコンストラクターの可塑性を表し、過負荷になる可能性があるため、ニーズに応じてより柔軟に構築できることを意味します。リロードがよくわからない友達は、ブロガーが書いたこの記事を読んでください。 初心者向け C++ 入門 (2) - CSDN ブログ

1.3 コンストラクターの使用 

例として日付クラスを考えてみましょう。年、月、日の基本変数を作成してから、コンストラクタと出力関数を作成します。ただし、注意すべき点は、コンストラクタの作成にはデフォルトのコンストラクタが必要であるということです。場合によっては、コンパイラは変数を単純に初期化できず、次の図に示すエラーを報告します。

デフォルトのコンストラクターとは何ですか? 私の考えでは、3 つのタイプがあります。

1. コンストラクターにデフォルト値を記述して完全なデフォルトを実現します。これにより、パラメータのない変数を作成したまま変数を初期化できます。

2. デフォルトにオーバーロードを使用する 

 3.宣言と同時に初期化する 

コンストラクターを作成した場合、コンパイラは作成した宣言を使用せず、作成したコンストラクターを直接呼び出します。コンストラクターの作成が完了していない場合は、エラーが報告されます。図に示すように:

ブロックした後は、ステートメントを通常どおり使用できます。

結論は:

一般に、デフォルト コンストラクターは、完全なデフォルトなど、パラメーターを渡さずに呼び出すことができる関数を指します。

ブロガーは、メソッド 1 を使用してコンストラクターを作成することを推奨していますが、メソッド 2 と 3 で作成されたデフォルトのコンストラクターはあまり規則的ではありません。

詳細:

メソッド 1 とメソッド 2 は同時に存在できません。そうしないと、コンパイラに曖昧さが生じます。   メソッド 1 とメソッド 2 は両方とも、宣言された形式で共存できることに注意してください。これは、コンストラクターが存在すると、コンパイラーは宣言された初期化を無視してコンストラクターの内容を呼び出すためです。

1.4 ビルトインタイプとカスタムタイプの構造詳細

まず、組み込み型とは何かについて話しましょう。組み込み型とは、int、double、float など、言語に付属する型を指します。カスタム型は、ユーザー自身が定義する型であり、理解しやすいです。 、クラスなどのタイプ。ただし、注意しなければならない点が 1 つあります。C++ では、コンパイラーはカスタム型に対してはデフォルトのコンストラクターを呼び出しますが、組み込み型に対しては呼び出しません。

#include<iostream>
#include<stdlib.h>
using namespace std;
class Stack
{
public:
	Stack(int capacity=10)
	{
		_capacity = capacity;
		_top = 0;
		_s = (int*)malloc(sizeof(int)*_capacity);
	}
private:
	int _top;//栈顶元素的位置
	int _capacity;//容量
	int* _s;//栈
};
class test
{
public:
private:
	Stack s1;
	Stack s2;
	int a;
};
int main()
{
	test t1;
}

テストはデストラクターを作成しませんでしたが、カスタム型メンバーのデフォルト コンストラクターを呼び出して、対応するデータが初期化されたことがわかります。注意深い学生なら、 a も初期化されていることがわかりますが、これはランダムな値であるべきではないでしょうか。私はそれを処理しませんでした。はい、ランダムな値であるはずですが、ブロガーは vs2019 コンパイラを使用してコードを書きました。高度すぎてブロガー向けに直接最適化されたため、現象は確認できませんでした。 vs2013 でこのコードを記述する場合、この変数はランダムな値である必要があります。興味のある友達は試してみてください。

2. デストラクター

1. デストラクタが存在するのはなぜですか?

コンストラクターについて話した後、デストラクターについて話しましょう。コンストラクターはクラスの作成時にクラスを初期化するため、デストラクターはクラスのライフ ドメインが終了したときにターゲットをクリーンアップします。つまり、破棄します。たとえば、シーケンスを書きました。 table, これは大きな領域を malloc します。その後、メモリ リークを避けるために、プログラムの終了前にこの大きな malloc 領域を解放する必要があります。したがって、一部のクラスを破棄するには destroy 関数が必要です。しかし、繰り返しになりますが、何かを書いてもそれを使用するのを忘れるのはよくあることです。そこで、C++ では、対応するクラスが生存領域を離れるときに破棄できるようにするデストラクターという関数が生まれ、安全性が確保されました。

2. デストラクタの特徴

1. デストラクター名には、クラス名の前に文字 ~ が付きます。
2. パラメータも戻り値の型もありません。
3. 明示的に定義されていない場合、システムはデフォルトのデストラクタを自動的に生成します。注: デストラクターはオーバーロードできません。
4. オブジェクトのライフサイクルが終了すると、C++ コンパイル システムは自動的にデストラクターを呼び出します。

まず 1 番目の点について説明します。1 番目の点は理解しやすいです。つまり、クラスの前にチルダ~があるということです。2 番目の点はコンストラクタに似ていますが、より厳密です。パラメータを持つことさえできません。3 番目の点です。 A クラスはデストラクターを 1 つだけ持つことができることを意味します

3. デストラクターを使用する

スタックを例に挙げます

#include<iostream>
#include<stdlib.h>
using namespace std;
class Stack
{
public:
	Stack(int capacity=10)
	{
		_capacity = capacity;
		_top = 0;
		_s = (int*)malloc(sizeof(int) * _capacity);
	}
	~Stack()
	{
		free(_s);
		_s = nullptr;
		_top = 0;
		_capacity = 0;
		cout << "以下为调用析构函数结果" << endl;
		cout << _s << endl;
		cout << _capacity << endl;
		cout << _top << endl;
	}
	void print()
	{
		cout << _s <<endl;
		cout << _capacity << endl;
		cout << _top << endl;
	}
private:
	int* _s;
	int _capacity;
	int _top;
};
int main()
{
	Stack s1;
	s1.print();
}

3. 次号の予告

次回は、QAQ のコピー コンストラクターと演算子のオーバーロードについて説明します。 

さて、今日の共有はここで終わります。訪問して読んでくださった皆さん、ありがとうございました。皆さんの明るい未来を祈っています。O(∩_∩)O 


 

おすすめ

転載: blog.csdn.net/fq157856469/article/details/134190755