クラスとオブジェクト
1. クラス定義
クラスとはオブジェクト指向言語に特有の構文であり、オブジェクト指向言語ではすべての変数や関数を総称してオブジェクトと呼び、クラス内にオブジェクトが存在することがあります。
文法
class ClassName
{
// 类体:由成员函数和成员变量组成
void Init();
int a;
};
//class为定义类的关键字,ClassName为类名,{}中为类的主题,注意类定义结束时后面分号不能省略。
//类中的内容称为类的成员:类的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。
クラスの定義方法
- 宣言と定義はすべてクラス本体に配置されます (注: メンバー関数がクラスで定義されている場合、コンパイラがそれを呼び出す可能性があります)。
// 成员函数声明定义都在类中
class xty
{
public:
void Print()
{
cout << "defined in class" << endl;
}
private:
int a;
int b;
};
- クラスの宣言は .h ファイルに配置され、メンバー関数は .cpp ファイルで定義されます。注: メンバー関数の名前を定義する前に、クラス名を追加する必要があります::
// .h文件
class xty2
{
public:
//声明
void Print();
private:
int a;
int b;
};
// .cpp定义
void xty2::Print()
{
cout << "defined in class" << endl;
}
エンジニアリング プロジェクトの実践では、宣言と定義を別々に扱うことをお勧めします。
構文が正しいことを示す記述がありコンパイル可能、定義があればリンク時にシンボルテーブルからアドレスが分かりリンク可能
2. クラスアクセス修飾子
アクセス修飾子: 1.public (パブリック); 2.protected (保護); 3.private (プライベート)
2.1 アクセス修飾子の特徴
- パブリックに変更されたメンバーには、クラスの外部から直接アクセスできます。
- 保護されたメンバーとプライベートに変更されたメンバーには、クラスの外部から直接アクセスすることはできません
- アクセス権の範囲は、このアクセス修飾子の出現から次のアクセス修飾子の出現までとなります。
- アクセス修飾子がない場合、スコープはクラスの終わりである } です。
- デフォルトのアクセス権限はクラスのプライベート、構造体はパブリックです(構造体はCと互換性があるため)
class Xty
{
public:
void Print()
{
cout << "defined in class" << endl;
}
private:
int a = 10;
int b;
int c;
};
int main()
{
//声明xp对象
Xty xp;
xp.a = 10; //报错,因为a 为私有,所以对xp.a不可访问
int z = xp.a; //报错,因为a 为私有,所以对xp.a不可访问
xp.Print(); //可以运行,Print成员函数为公有,因此可以在类外面访问
return 0;
}
この目的は、外部メンバーがメンバー変数を任意に変更できないように、メンバー変数をプライベートとして、メンバー関数をパブリックとして設定することです。
2.2 構造体とクラスの違い
- まず、struct は C 言語のキーワードです。C 構文との互換性を保つために、C++ では struct クラスのデフォルトの権限を public にし、クラス外のオブジェクトからアクセスできるようにします。class はデフォルトで private ですが、授業外では気軽にアクセスできません。
3. 三大特性
C++ には、継承、カプセル化、ポリモーフィズムという 3 つの主要な機能があります。
3.1 パッケージ
データとデータの操作方法を有機的に組み合わせ、オブジェクトの属性と実装の詳細を隠し、外界に公開されたインターフェイスを通じてのみオブジェクトと対話します。カプセル化は本質的に一種の管理であり、ユーザーがクラスをより安全かつ便利に使用できるようにします。
4. クラスの範囲
クラスは新しいスコープを定義し、クラスのすべてのメンバーはクラスのスコープ内にあります。クラス外のメンバーを定義する場合は、:: スコープ修飾子を使用する必要があります。
class Xty
{
public:
void Print();
private:
int a = 10;
int b;
int c;
};
//在类外面定义成员时,需加上域名,来说明Print是属于Xty这个域里面的
void Xty::Print()
{
cout << "hello world!" << endl;
}
5. クラスのインスタンス化
型からクラスを作成することをクラスのインスタンス化といいます。
- クラスはオブジェクトを記述するモデルであり、定義されたクラスは実際のメモリ領域を割り当てません。
- クラスは複数のオブジェクトをインスタンス化 (作成) でき、オブジェクトは実際の物理空間を占有し、クラス メンバー変数を格納します。
class Xty
{
public:
void Print();
int a;
int b;
int c;
};
//在类外面定义的成员函数
void Xty::Print()
{
cout << "hello world!" << endl;
}
int main()
{
//Xty的类创建出xp的对象
Xty xp;
//是给xp的对象赋值,而不是给类赋值
xp.a = 10;
xp.b = 20;
xp.Print();
return 0;
}
6. クラスオブジェクトモデル
コンパイラはオブジェクトをどのように保存しますか?
まずコード例を見てみましょう。
//类中既有成员变量又有成员函数
class X1
{
public:
void Print()
{
cout << "hello world" << endl;
}
private:
char a;
};
//类中只有成员变量
class X2
{
private:
int a;
};
//类中什么也没有
class X3
{
};
int main()
{
X1 x1;
X2 x2;
X3 x3;
cout<<"x1 : " << sizeof(x1) << endl; // 1
cout<<"x2 : " << sizeof(x2) << endl; // 4
cout<<"x1 : " << sizeof(x3) << endl; // 1
return 0;
}
観察すると、オブジェクトのメンバ変数は記憶領域を占有しますが、メンバ関数はオブジェクトの領域を占有せず、クラス オブジェクトに何もない場合は、1B を使用して領域を占有することがわかります。物体の存在。
実際: メンバー変数とメンバー関数は別々に格納され、メンバー変数のみがオブジェクトの格納スペースを占有し、このクラスのすべてのオブジェクトのメンバー関数は共通コード領域に格納され、すべてのオブジェクトがコードを共有します。
7. このポインタ
まず、次のコード部分を見てください。
class Time
{
public:
void Init(int h, int min, int s)
{
_h = h;
_min = min;
_s = s;
}
void Print()
{
cout << _h << ":" << _min << ":" << _s << endl;
}
private:
int _h;
int _min;
int _s;
};
int main()
{
Time t1;
Time t2;
t1.Init(10, 20, 3);
t2.Init(5, 10, 1);
t1.Print(); // 10:20:3
t2.Print(); // 5:10:1
}
メンバー関数はパブリック領域にあり、メンバー関数には Print 関数と Init 関数があるため、C++ は t1.Init() 関数を呼び出すとき、t1 オブジェクトを使用するかどうかをどのようにして知るのでしょうか。 t2オブジェクト?
回答: C++ コンパイラは、各「非静的メンバー関数」に隠しポインター パラメーターを追加し、ポインターが現在のオブジェクト (関数の実行時に関数を呼び出すオブジェクト) と、その関数内のすべての「メンバー変数」を指すようにします。関数本体 クソ、すべてはこのポインタを通じてアクセスされます。すべての操作はユーザーにとって透過的である、つまり、ユーザーが操作を渡す必要がなく、コンパイラーが自動的に操作を完了するだけです。このポインターが「this ポインター」です。
7.1 このポインタの特徴
- このポインターの型: メンバー関数内のクラス型 *const は、このポインターに値を割り当てることができません。
- メンバー関数内でのみ使用できます。
- this ポインタの本質はメンバ関数の仮引数であり、オブジェクトがメンバ関数を呼び出す際に、オブジェクトのアドレスが実引数としてこの仮引数に渡されます。したがって、 this ポインタはオブジェクトに格納されません。
- this ポインタは、「メンバー関数」の最初の隠しポインタ パラメータです。通常、これはコンパイラによって ecx レジスタを通じて自動的に渡され、ユーザーが渡す必要はありません。
this ポインターは存在しますが、これはコンパイラーによって自動的に行われます。使用してもしなくても構いません。
実パラメータと仮パラメータはこのポインタを明示的に渡したり受け入れたりすることができず、エラーが報告されます (コンパイルできません)。以下の図に示すように、
ただし、次の図に示すように、 this ポインターはメンバー関数内で使用できます (コンパイル可能)。
7.2 このポインタに関連する問題
- このポインタはどこにあるのでしょうか? このポインタは仮パラメータであり、仮パラメータはスタック領域に格納される。
- このポインタは null であってもよいでしょうか? this ポインタは空にすることができます。メンバ関数にアクセスするとき、メンバ関数はパブリック領域に直接アクセスして関数を見つけますが、逆参照によって関数を見つけることはないため、null ポインタを逆参照することはありません。