目次
1. クラスの概念
1. それは何ですか?
これは、同じプロパティと動作を持つものを抽象化したものです。
2. なぜですか?
関連するデータと関数をまとめて管理しやすくします。クラスはオブジェクト指向プログラミングの前提です。
3. 使い方は?
記述すべきものの属性と動作(関数で実装)をまとめてクラスを形成します。
2つ目はクラスの紹介です
1. 構造体がクラスにアップグレードされる
C++ では、struct は C 言語の構造体の構文と互換性があるだけでなく、C++ のクラスにアップグレードされます。
2. クラス内で関数を定義可能 クラスには、
メンバー変数とメンバー関数の 2 つの部分が含まれます。したがって、C++ では、構造体で変数を定義できるだけでなく、関数も定義できます。
3.class はクラスを定義することもできます
struct に加えて、 class は C++ でクラスを定義するために使用することもでき、class は C++ でクラスを定義するためにより一般的に使用されます。
拡張機能: C と C++ の構造体の微妙な違い
1. C の場合、typedef を使用して構造体の名前を変更すると、最後の行以降で有効になります。構造体で使用される構造体名には、struct も付ける必要があります。
2. C++ では、typedef の名前変更を使用しなくても、クラス名をクラス内で直接使用できます。
3. クラス定義
1. クラスを定義する
class className //法一 { // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号 struct structName //法二 { // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号
class (または struct) はクラスを定義するためのキーワード、className (structName) はクラス名、{} はクラスの本体です。ただし、クラス定義の最後のセミコロンは省略できません。クラス本体の内容はクラスのメンバーと呼ばれ、クラス内の変数はクラスの属性またはメンバー変数と呼ばれ、クラス内の関数はクラスのメソッドまたはメンバー関数と呼ばれます。
2. 構造体とクラスの違い
C++ では、クラスを定義するために struct または class を使用できます。この 2 つの違いは、
修飾子が追加されていない場合、struct はデフォルトで public になり、class はデフォルトで private になることです。
拡張子: クラスアクセス修飾子
3. クラス内のメンバ関数の宣言と実装の分離
a. メンバー関数の 宣言と 実装は すべてクラス本体に配置されます 注: メンバー関数がクラス内で定義されている場合、コンパイラはそれを インライン関数として扱う ことがあります 。
b. メンバー関数の宣言は .h ファイルに配置され、メンバー関数の実装は .cpp ファイルに配置されます。(注: 宣言と実装が分離されている場合、宣言はクラス ドメイン内にあるため 、クラスを見つけるために 定義中に メンバー関数の名前の前にクラス名とドメイン スコープ修飾子 (::) を追加する必要があります。 )
大規模なプロジェクトでは、通常の関数と同様に、クラス内のメンバ関数の宣言と実装を分離することが推奨されますが、クラス内のメンバ関数の宣言と定義を分離する意義は、コードを読みやすくするためです。
拡張 1.メンバー関数がクラスで定義されている場合、コンパイラーはそれをインライン関数として扱うことができます。
宣言と実装が分離されると、クラスのメンバー関数はインライン関数とみなされなくなります。(インライン関数の宣言と実装は分離できず、インライン関数はシンボルテーブルに入らず、リンク時に宣言から実装のアドレスを見つけることができません)
拡張 2. 宣言と定義が分離されている場合: 定義時にクラスのドメイン名を追加しないと、クラス ドメインとグローバル ドメインに同じ名前の 2 つの関数が表示されますが、これは実行可能であり、構成要素にはなりません。関数のオーバーロード。(異なるドメインの関数はオーバーロードを構成しません)
4.カプセル化とクラスアクセス修飾子
1. カプセル化
1. それは何ですか?
これは本質的にデータの管理です。オブジェクトの属性とメソッドの実装の詳細は隠蔽され、インターフェイスのみが外部に公開され、プログラム内の属性の読み取りと変更のアクセス レベルが制御されます。
2. なぜですか?
プログラムの安全性と保守性(改善の容易さ)を向上させます。
3. どうやって行うのですか?
C++ でカプセル化を実現する方法: クラスを使用して属性とメソッドを組み合わせ、アクセス権を設定することでそのインターフェイスを外部ユーザーに選択的に提供します。
2. クラスアクセス修飾子
パブリック(パブリック)、プライベート(プライベート)、プロテクト(保護)
5. クラスの範囲とライフサイクル
1. 授業の範囲
クラスは新しいスコープを定義し、クラスのすべてのメンバーはクラスのスコープ内にあります。クラス外のメンバーを定義する場合は、::スコープ演算子を使用して、メンバーがどのクラス ドメインに属しているかを示す必要があります。
2. クラスのライフサイクル
クラスのライフサイクルは格納場所に関係します。たとえば、グローバル クラスと静的クラスは静的領域に格納され、そのライフ サイクルはプロジェクト全体です。関数内のクラスのライフ サイクルはこの関数に従います。 ..
6. クラスのインスタンス化
【コンセプト】
クラスを使用してオブジェクトを作成するプロセスは、クラスのインスタンス化と呼ばれます。クラスは複数のオブジェクトをインスタンス化できます。
クラスはスペースを占有せず、オブジェクトにインスタンス化された後、クラス メンバー変数の格納 に使用されるスペースを占有します。ただし、クラスを通じてオブジェクトが占めるスペースのサイズを計算することもできます。
同様に、構造体の定義にはスペースは必要ありません。構造体変数の定義のみにスペースが必要ですが、構造体の名前の sizeof を使用して、構造体変数が占めるスペースを計算することもできます。
1. 暗黙的な作成
コンパイラによってデフォルトのコンストラクターを呼び出すことによってスタック上に作成されます。
class A{}; A a;
2. 明示的な作成
コード内でコンストラクターをアクティブに呼び出し、スタック上に作成します。
class A{}; A a = A();
3. 明示的な新規作成
new キーワードは、ヒープ内にメモリ作成を割り当てるために使用されます。
class A{}; A* pa = new A();
新しいオブジェクトはポインタによって受信される必要があり、メモリを解放するにはオブジェクトを明示的に削除する必要があります。
7. クラスとオブジェクトの格納方法
1. メンバ関数の格納方法の推測
メンバ関数の格納方法推測1:メンバ関数のアドレスとメンバ変数の両方を格納する
問題は、呼び出されるメンバー関数がすべて同じであるため、オブジェクトごとにメンバー関数のアドレスを格納する必要がないことです。
メンバ関数の格納方法推測2:メンバ関数のアドレスを別途テーブルに格納し、格納時に追加テーブルのアドレスを格納する
このアプローチに問題はありませんが、ここでは使用しません。
メンバ関数の格納方法に関する推測3:メンバ変数のみを格納し、メンバ関数はパブリックコード領域に一律に格納する。
このスキームはメンバ関数の格納スキームです。関数のアドレスは実行時にはオブジェクト内で見つかりませんが、関数のアドレスはコンパイルおよびリンク時に関数名に従ってパブリック コード領域で見つかります。
したがって、クラスが次の状況に遭遇した場合でも、プログラムはクラッシュしません。(メンバー関数のアドレスはクラス内に見つからず、パブリック コード領域で見つかるため、クラスは nullptr としてインスタンス化され、引き続きメンバー関数を呼び出すことができます)
2. メモリ内のクラス内のメンバーの分布
1) クラス内の通常のメンバ変数 ------------ スタック
2) クラス内の静的メンバ変数 ------------ 静的領域
3) クラス内の参照変数------------ 参照される変数を見てください。
4) クラス内の const 変数 ------------ stack (const の変更は変数を読み取り専用に制限するだけです。本質は依然として Variable であり、格納場所は変数自体に依存するため、const によって変更されたローカル変数はまだスタック上にあり、ポインタを介して変更できます。)5) クラスのメンバ関数 ------------ 通常のメンバ関数と静的メンバ関数はすべてコード領域にあります
3. メモリ内のクラスの保存場所
クラスはメモリに格納されません。クラスは、オブジェクトの作成方法、必要なバイト数、およびオブジェクトの破棄方法をプログラムに指示するための単なるテンプレートです。
クラスからインスタンス化されたオブジェクトはメモリに保存されます。
4.メモリ内のオブジェクトの保存場所
3.1 グローバルオブジェクト
グローバルオブジェクトはグローバル(静的)記憶領域106に格納され、プログラム終了後にシステムコールデストラクタにより解放される。
3.2 ローカルオブジェクト
ローカル オブジェクトはスタックに保存されます。スコープが終了するとその寿命は終了し、そのデストラクターが自動的に呼び出されます。つまり、オブジェクトは自動的にクリーンアップされます。
3.3 静的ローカルオブジェクト
静的ローカル オブジェクトはグローバル (静的) ストレージ領域 に格納され、スコープが終了した後も存続します。つまり、プログラム全体が終了するまでオブジェクトのデストラクターは現時点では呼び出されません。
3.4 動的オブジェクト
動的オブジェクト (つまり、新しいオブジェクト) はヒープに格納され、削除されるとその寿命が終了します。動的オブジェクトの作成に使用されるポインターはスタックに保存されます。
注: 新しいオブジェクトの場合は、delete を使用してデストラクターを明示的に呼び出す必要があります。そうしないと、プログラムがデストラクターを呼び出さず、メモリ リークが発生します。
[コードデモ]
class A{ }; class B{ }; class C{ }; class D{ }; A a; //全局对象 int main(){ B b; //局部对象 static C c; //静态局部对象 D *d = new D; //动态对象 delete d; return 0; }
【メモリレイアウト】
8. クラスのサイズを計算します
1. メンバ変数のサイズを計算する
構造体と同様に、クラスもメモリ アライメントルールに従います。2 番目のメンバー変数から開始して、開始位置を計算する必要があり、それ自体のサイズとデフォルトのアライメント番号 (デフォルトのアライメント番号) の間で小さい方が選択されます。 VSコンパイラは8)のものです。最後に、クラス全体も整列する必要があります。クラスのサイズは、デフォルトの整列の整数倍でなければなりません。
sizeof がクラスのサイズを計算するとき、静的メンバー変数のサイズは無視されます。
2. メンバー関数のサイズを計算する
クラスのサイズを計算するとき、メンバー関数は考慮されないため、関数ポインターのサイズを追加する必要はありません。
3. 空のクラスのサイズを計算する
なお、メンバ変数を持たないクラス(空のクラスも含む)のサイズは1バイトであり、データは格納されず、スペースの占有、オブジェクトの存在の識別、オブジェクトの区別が目的です。
要約:
クラスのサイズの計算とは、クラス内のすべての(非静的) メンバー変数 のサイズをメモリに合わせて計算することです。