諌めではなく過去を認識し、未来を知ることで追求できる
C++プログラマー、2024年電子情報系大学院生
クラスの 6 つのデフォルトのメンバー関数
クラス内にメンバーが存在しない場合、そのクラスは空のクラスと呼ばれますが、空のクラスは本当の意味で何も存在しないことを意味するわけではなく、コンパイラはデフォルトで上記のデフォルトの 6 つの関数を生成します。メンバー関数。
コンストラクタ
特性
コンストラクターは特別なメンバー関数です。コンストラクターは構築と呼ばれていますが、コンストラクターの主なタスクはオブジェクトを作成するためのスペースを開くことではなくオブジェクトを初期化することであることに注意してください。
その特徴は次のとおりです。
- 関数名はクラス名と同じです
- 戻り値がないため、戻り値を記述する必要はありません
- オブジェクトがインスタンス化されると、コンパイラは対応するコンストラクターを自動的に呼び出します。
- コンストラクターはオーバーロードできる
自動生成されたコンストラクターは、デフォルトでは組み込み型を初期化しません。
コンストラクターは、クラス名と同じ名前を持つ特別なメンバー関数であり、クラス型オブジェクトの作成時にコンパイラーによって自動的に呼び出されます。
各メンバーが適切な初期値を持ち、オブジェクトのライフサイクル全体を通じて 1 回だけ呼び出されるようにするため。
デストラクタ
1. デストラクタの名前は、クラス名の前に文字 ~ を追加します。2. パラメーターも戻り値の型もありません。3. クラスにはデストラクターを 1 つだけ含めることができます。明示的に定義されていない場合、システムはデフォルトのデストラクターを自動的に生成します。注: デストラクターはオーバーロードできません4. オブジェクトのライフサイクルが終了すると、C++ コンパイル システムは自動的にデストラクターを呼び出します。
コンストラクターとデストラクターを使用すると、初期化関数と破棄関数の作成を忘れることを恐れません。
class Date
{
public:
void Print()
{
cout<<_year<<"-"<<_month<<"-"<<_day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
d1.Print();
return 0;
}
コンパイラーはデフォルトでコンストラクターを生成し、組み込み型は処理されず、カスタム型はデフォルトの構造を呼び出します (一部のコンパイル済みコンストラクターは、
デバイスが自動的に処理します)
一般に、組み込み型のスレーブ メンバーがある場合は、コンパイラでは生成できない独自のコンストラクターを作成する必要があります。
すべてカスタム型のメンバーであるため、コンパイラーに自動的に生成させることを検討できます。
解決:
class Date
{
public:
void Print()
{
cout<<_year<<"-"<<_month<<"-"<<_day << endl;
}
private:
//C++11支持,这里不是初始化,因为这里只是声明
//这里给的是默认的缺省值,给编译器默认构造函数用的
int _year = 1;
int _month = 1;
int _day = 1;
};
int main()
{
Date d1;
Date d2;
d1.Print();
return 0;
}
結論は:
1. 通常の状況では、動的に適用されるリソースがあり、デストラクターを自分で記述する必要があります。
2. 動的に適用されるリソースがないため、デストラクターを記述する必要がありません。
3. すべてカスタム タイプの構造であり、これらのタイプはデフォルトの構造を定義します。
質問:
C++ の構造体とクラスの違いは何ですか?
C++ は C 言語と互換性がある必要があるため、C++ の struct を構造体として使用でき、C++ の struct も構造体として使用できます。
クラスを定義するために使用できます。これはクラス定義クラスと同じです。違いは、構造体によって定義されたクラスであり、デフォルトのアクセス権限は public であることです。
class で定義されたクラスのデフォルトは private です
アクセス修飾子の説明:
1. public によって変更されたメンバーはクラス外から直接アクセスできます
2. 保護されたメンバーとプライベートな変更されたメンバーには、クラスの外部から直接アクセスすることはできません
3. アクセス権の範囲は、アクセス修飾子が出現した位置から次のアクセス修飾子が出現するまでとなります。
4. 後ろにアクセス修飾子がない場合は、 } クラスの終わりまで終了します
構造はどのように調整されますか? なぜメモリを調整するのか?
①. 最初のメンバは構造体からのオフセットが0のアドレスにあります。
②.他のメンバ変数は、ある数値(アライメント番号)の整数倍のアドレスにアライメントされている必要があります。
③. 構造体の合計サイズは、最大アライメント数の整数倍です。
④.入れ子構造の場合、入れ子構造は自身の最大アライメント数の整数倍にアライメントされ、構造全体のサイズはすべての最大アライメント数(入れ子構造のアライメント数を含む)の整数倍となります。構造)。
このポインタ
このポインタの導出
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
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;
Date d2;
d1.Init(2023,7,6);
d1.Print();
d2.Init(2022,7,6);
d2.Print();
return 0;
}
質問: Date クラスには Init と Print という 2 つのメンバー関数があり、関数本体では異なるオブジェクト間の区別がありません。そのため、d1 が Init 関数を呼び出すとき、この関数はどのようにして d2 オブジェクトではなく d1 オブジェクトを設定するかを知るのでしょうか。物体?
C++ では、この問題を解決するために this ポインターを導入しています。つまり、C++ コンパイラーは、各「非静的メンバー関数」に隠しポインター パラメーターを追加し、ポインターが現在のオブジェクト (関数の呼び出し時に関数を呼び出すオブジェクト) を指すようにします。実行中)、関数本体内のすべてのメンバー変数操作には、このポインターを介してアクセスされます。すべての操作がユーザーに対して透過的であるというだけです。つまり、ユーザーが操作を渡す必要がなく、コンパイラーが自動的に操作を完了します。
このポインタの特徴は次のとおりです。
1. このポインタの型: クラス型 *const、つまりメンバー関数では、このポインタに値を割り当てることはできません。
2. メンバー関数内でのみ使用可能
3. このポインタは本質的にメンバ関数の仮パラメータであり、オブジェクトがメンバ関数を呼び出すとき、オブジェクトのアドレスが実際のパラメータとして使用されます。
this パラメータに渡されるパラメータ。したがって、 this ポインタはオブジェクトに格納されません
4. this ポインタは、メンバー関数の最初の暗黙的なポインタ パラメータです。一般に、コンパイラは ecx レジスタを使用して自動的に
動的転送、ユーザー転送は不要
C++ は、基本型/組み込み型 (int、char、ポインター、float など)、カスタム型 (構造体、クラスなど) に分かれています。
定義された型)、組み込み型は処理されず、カスタム型はそのデフォルトのコンストラクターを呼び出します。
this ポインタは仮パラメータと実パラメータの間で明示的に渡すことはできませんが、関数内では明示的に使用できます。
関数がインスタンス化されると、自動的に呼び出されます。
コピーコンストラクター
コンセプト
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Date(const Date& d) // 正确写法
Date d2(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;
}
class Time
{
public:
Time()
{
_hour = 1;
_minute = 1;
_second = 1;
}
Time(const Time& t)
{
_hour = t._hour;
_minute = t._minute;
_second = t._second;
cout << "Time::Time(const Time&)" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d1;
// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构
造函数
Date d2(d1);
return 0;
}