1. C++ のクラス
1. クラスの 3 つの特徴:
-
パッケージ:
- 1. 関数型関数インターフェイスをクラスにカプセル化します。
- 2. データメンバーをクラスにカプセル化する
-
継承:
- 1. サブクラスは親クラスの関数インターフェイスやデータを継承するため、コードの再利用性を向上させるためにインターフェイスを再開発する必要はありません。
-
多態性:
- 同じ操作が異なるオブジェクトに作用し、異なる結果を得るために異なる解釈が行われる可能性があります。コードの柔軟性と保守性が向上します。
2. オブジェクト指向プログラミングの利点
- 1. コードの変更と保守が簡単です (各オブジェクトが独立しているため、オブジェクトのコンテンツを変更するだけで済みます)
- 2. コードの再利用性 (継承、ポリモーフィズム、関数のオーバーロード) を改善し、コードを大幅に削減します。
- 3. 複雑なプログラムをより適切に設計できる
2 番目に、C++ でのクラスの定義
class 类名
{
//成员列表
}
これは最も簡単な定義方法ですが、この方法で定義されたクラスには意味がありません。なぜならクラスのメンバーは、プライベートメンバー、外の世界はアクセス不可の。
1. 一般クラスの定義方法
class 类名
{
public : //共有成员,外界可以访问
protected : //保护成员,只有派生类可以访问
private : //私有成员,只有当前类内部可以访问
}
クラスの定義例:
class base
{
public:
int a; //外界可以访问,因为是共有成员
protected:
int b; //子类可以访问,因为是保护成员
private:
int c; //只有类的内部可以访问 ,因为是私有成员
};
3 番目に、C++ のクラスのコンストラクター
1. コンストラクター:
- 1. 関数名はクラス名と同じです
- 2.関数には戻り値がありません
- 3. 関数を呼び出す必要はありません。オブジェクトの作成時に自動的に呼び出されます。
2. コンストラクターの役割:
- オブジェクトの作成時にオブジェクト内のデータ メンバーを変更するために使用されます。初期化します。
3. コンストラクターの構文:
class 类名
{
public:
类名() //构造函数
{
}
}
例子:
class base
{
public:
base()
{
cout << "调用构造函数" << endl;
}
}
知らせ:
- コンストラクタに書かなければなりません公共の場オブジェクトの作成時にコンストラクターが自動的に呼び出されるからです。パブリック領域にない場合は呼び出すことができないため、オブジェクトの作成が失敗します。
- ユーザーがコンストラクターを作成しないと仮定すると、システムはパラメーターのないコンストラクターを自動的に生成します。
ヒント:
- 1. コンストラクターもサポート関数のオーバーロード
- 2. コンストラクターもデフォルトパラメータのサポート
演習: 共通のメンバー名、保護されたメンバーのお金、およびプライベートのメンバー ID を使用して学生クラスを設計し、これらのデータ メンバーを初期化するコンストラクターを設計します。そして出力インターフェースを設計します。
#include <iostream>
using namespace std;
extern "C"
{
#include <string.h>
}
class student
{
public:
student(const char *Name, int Money, int ID) : Money(Money), ID(ID)
{
strcpy(this->Name, Name);
}
void show()
{
cout << this->Name << this->Money << this->ID << endl;
}
char Name[32];
protected:
int Money;
private:
int ID;
};
int main()
{
student stu("张三", 100, 180);
stu.show();
}
4、このポインタ
効果:
- 慣れている区別する内側メンバーと外側メンバー
- ユーザーがオブジェクトを作成するたびに、このクラスは現在のクラスを指す this ポインターを自動的に生成します。最初の住所
base(int a,int b,int c)
{
//this->a 当前类-》a 成员
this->a=a;
this->b=b;
this->c=c;
}
//不使用 this 指针那么 a ,b ,c 变量的名字要重新修改!!
5. malloc と new の違い
#include <iostream>
using namespace std;
extern "C"
{
#include <stdlib.h>
}
class base
{
public:
base(int a)
{
cout << "调用based的构造函数" <<endl;
this->a = a;
}
void show()
{
cout << a << endl;
}
private:
int a;
};
int main()
{
//利用malloc分配base的空间
base *p = (base *)malloc(sizeof(base));
p->show();
//利用new分配base空间
base *q = new base(10086);
q->show();
}
知らせ:
- malloc を使用してクラス用のスペースを空けます。電話しませんクラスのコンストラクターにより、クラスのメンバーの初期化が失敗します。
- new を使用してクラスのヒープ領域を開きます。呼び出すことができますクラスのメンバーを初期化するコンストラクター
6. デストラクター
- 1. 関数名はクラス名と同じです。関数名の前に追加します。~
- 2. デストラクタには戻り値がありません。パラメータなし
- 3. オブジェクトが破壊されると、自動通話。デストラクターを使用して、クラス内のメンバーのスペースを解放できます。
効果:
- コンストラクターで初期化されたデータメンバーを解放するために使用されます。
知らせ:
- オーバーロードの基礎は関数パラメーターであり、デストラクターにはパラメーターがないため、デストラクターをオーバーロードできません。
- デストラクタも次のように書き込む必要があります。公共の場オブジェクトが破棄されると自動的に呼び出されるため
七、クラス内でのサイズ計算
バイトアライメントの原則:
構造のサイズ計算を確認します。
struct node
{
char a;
int b;
short c;
double d;
} //在64位的操作系统中计算该结构体的大小 -》24
要約:
- 構造体のスペース サイズはバイト アラインメントの原則に基づいており、32 ビット システムと 64 ビット システムでは異なります。具体的な位置合わせの原則については、上の表を参照してください。
クラス内のスペースサイズの割り当ては、構造体のサイズ割り当てと同じです。
//当前类中 最大的字节是 int 所以按照4字节对齐原则
class base
{
char a; //分配4个 char使用 1个剩下 3 个
short b; //剩下的3个可以提供2个给 short去使用 所以剩下1 个
int c; //重新分配 4 个空间
}; //->8
class base1
{
char a; //分配4个
int c; //分配4个
short b; //分配4个
}; //根据 4 自己对齐原则 -》 12
結論は:
- クラスのデータ メンバー、データ型を設計する場合、昇順に定義するには、この方法で定義されたクラスは最小のメモリ空間を占有します。
クラス内のサイズとメンバー属性の関係:
クラス内のサイズとメンバー関数の関係:
class base2
{
public:
void func() //在没有调用 func 的时候,b,c的空间是不会分配
{
//b 和 c 根本都不属于 base2类的空间中
int b;//func 里面的局部变量 ,局部变量是临时存在的
int c;
}
int a;
}; //4
結論は:
- クラス内のスペースのサイズは、クラス内のデータ メンバーにのみ関係し、クラス内のメンバー関数とは関係ありません。(仮想機能に加えて)
ヒント: 空のクラスのサイズは 1 です。
8、コンストラクターパラメータリストの初期化
効果:
- クラス内のデータ メンバーを初期化するために使用されるコンストラクター内の特別な初期化メソッド
ヒント:
- この初期化方法は万能薬ではないため、データ型が = 代入をサポートしていない場合、この方法は使用できません。配列、文字列などの列
9、コピーコンストラクター(キー、難しい)
システムによって自動的に生成されるシャロー コピー メソッド:
#include <iostream>
using namespace std;
class base
{
public:
base(int a, int b, int c) : a(a), b(b), c(c){
}
void show()
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
private:
int a, b, c;
};
int main()
{
base a(10, 20, 30);
a.show();
//通过一个对象去初始化另外一个人对象
base b = a;
//系统会自动生成一个浅拷贝构造函数,把a对象的数据赋值给b对象
b.show();
}
システムのコピー コンストラクターをオーバーライドします。
- コピー コンストラクターをオーバーライドするときは、パラメーターを次のように渡す必要があります。引用, この時点で、システムのデフォルトのコピー コンストラクターはオーバーライドされます。コピー コンストラクターを書き換えることで、次のことを実現できます。ディープコピー。
文法:
class 类名
{
public:
类名(类名 &a) //重写后的拷贝构造函数 ,
{
}
}
ヒント:
- ユーザーがコピー コンストラクターをオーバーライドすると、システムはシャロー コピー メソッドを自動的に生成しません。
#include <iostream>
using namespace std;
class base
{
public:
base(int a, int b, int c) : a(a), b(b), c(c){
}
base (base &a)
{
cout << "调用拷贝构造函数" << endl;
this->a = a.a;
this->b = a.b;
this->c = a.c;
}
void show()
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
private:
int a, b, c;
};
int main()
{
base a(10, 20, 30);
a.show();
//通过一个对象去初始化另外一个人对象
base b = a;
//系统会自动生成一个浅拷贝构造函数,把a对象的数据赋值给b对象
b.show();
}
十、ディープコピー
なぜディープコピーが必要なのでしょうか? ?
- 2 つのオブジェクトが入っているため、単一のアドレス空間を共有する。これは非常に危険です。
コピー コンストラクターを書き換えてディープ コピーを実装します。
#include <iostream>
using namespace std;
extern "C"
{
#include <string.h>
}
class base
{
public:
base (const char *str)
{
//分配p所指向的堆空间
p = new char[1024];
//把str数据赋值到堆空间中
strcpy(p, str);
}
//重写拷贝构造函数,实现深拷贝!!!!!
base (base &a)
{
cout << "调用重写后的拷贝构造函数,实现深拷贝"<< endl;
//分配p所指向的堆空间
p = new char[1024];
strcpy(p, a.p);
}
void show()
{
cout << "堆空间的地址" << (void *)p <<"内容" << p << endl;
}
char *p;
};
int main()
{
base a("hello");
a.show();
base b = a;
b.show();
}
ディープ コピーを使用すると、2 つのオブジェクトが操作するヒープ領域のアドレスが異なります。
11. クラス外で定義されたクラス内のメンバ関数
文法:
返回值 类名::函数名(参数列表)
{
}
-----------------------------------
例子:
class base
{
public:
void show(); //声明
};
//类外定义show 接口
void base::show()
{
cout << "show base" << endl;
}
演習: 関数メンバーの内部と外部の実装
#include <iostream>
using namespace std;
extern "C"
{
#include <string.h>
}
class base
{
public:
base(int size,const char *str);
base(base &a); //深拷贝函数
~base();
void show();
private:
int size;
char *p; //指向一块堆空间
};
base :: base(int size,const char *str)
{
cout << "base 构造函数" << endl;
this->size = size;
p = new char[size];
strcpy(p, str);
}
base :: base(base &a)
{
cout << "base 深拷贝构造函数" << endl;
p = new char[a.size];
strcpy(p, a.p);
}
base :: ~base()
{
cout << "base 析构函数" << endl;
delete []p;
}
void base :: show()
{
cout << p << endl;
}
int main()
{
base a(1024, "Hello");
a.show();
base b = a;
b.show();
}