1. クラスメンバーとしてのクラスオブジェクト
クラスは別のクラスのメンバーになることができます
コード:
#include <iostream>
using namespace std;
class phone {
public:
string shouji;
phone(string shouji1) :shouji(shouji1) {
cout << "phone的构造函数调用" << endl;
}
~phone() {
cout << "phone的析构函数调用" << endl;
}
};
class person {
public:
int age;
string name;
phone shouji;
//隐式转换相当于shouji=phone(shouji1)
person(int a, string name1, string shouji1) :age(a), name(name1), shouji(shouji1) {
cout << "person的构造函数调用" << endl;
}
~person() {
cout << "person的析构函数调用" << endl;
}
};
void fun() {
person p(23, "小明", "苹果");
}
int main() {
fun();
return 0;
}
知らせ:
クラスを作成するときは、最初に含まれるクラスのコンストラクタが呼び出され、次に外部クラスのコンストラクタが呼び出されます。1 を破棄する場合はその逆で、最初に外部クラスが破棄され、次に内部クラスが破棄されます。 。
2. 静的メンバー
静的メンバーは、メンバー変数の前に static キーワードを追加することによって静的メンバーと呼ばれます。
静的メンバーは、静的メンバー変数と静的メンバー関数に分類されます。
2.1 静的メンバー変数
。すべてのオブジェクトが同じデータを共有する
。メモリはコンパイル段階で割り当てられます。
。クラス内宣言、クラス外初期化・静的メンバー関数
静的メンバーはクラスの外部で初期化する必要があります。そうしないと、コンパイラーは静的メンバーが宣言されているだけで実際には定義されていないとみなして、リンク エラーが発生します。
コード:
#include <iostream>
using namespace std;
class person {
public:
static int age;
};
int person::age = 10;
void fun() {
person p;
p.age = 90;
person p1;
cout << p1.age << endl;
}
int main() {
fun();
return 0;
}
静的メンバー変数には、オブジェクトだけでなくクラス名からもアクセスできます。静的メンバー変数にもアクセス権があります。
コード:
#include <iostream>
using namespace std;
class person {
public:
static int age;
};
int person::age = 10;
void fun() {
person p;
p.age = 90;
cout << person::age << endl;
}
int main() {
fun();
return 0;
}
2.2 静的メンバー関数
。すべてのオブジェクトは同じ機能を共有します
。静的メンバー関数は静的メンバー変数にのみアクセスできます
コード:
#include <iostream>
using namespace std;
class person {
public:
static int age;
static void fun(int a) {
age = a; //只能调用静态成员变量
cout << "静态函数fun调用" << endl;
}
};
int person::age = 100;
void dioayong() {
person p;
p.fun(99); //对象调用
person::fun(66); //类名调用
cout << p.age << endl;
}
int main() {
dioayong();
return 0;
}
同様に、静的メンバー関数もクラス名を通じて呼び出すことができますが、静的メンバー関数は静的メンバー変数のみを呼び出すことができることに注意してください。
3.このポインタ
3.1 メンバ変数と関数の格納
C++ では、クラス内のメンバー変数とメンバー関数は別々に格納されます。
非静的メンバー変数のみがクラスのオブジェクトに属します
C++ では、空のクラスも 1 バイトを占有します。また、C++ コンパイラは、メモリ内のオブジェクトの位置を区別するために、空のオブジェクトごとにバイト領域を割り当てます。
コード:
#include <iostream>
using namespace std;
class person {
};
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
このクラスにはメモリアライメントの機能もあります
コード:
#include <iostream>
using namespace std;
class person {
public:
int a;
char b;
};
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
さらに、メンバー関数も静的メンバー変数もクラスに格納されません。つまり、非静的メンバー変数のみがクラスに格納されます。
コード:
#include <iostream>
using namespace std;
class person {
public:
int a;
static int b;
void fun() {
cout << "fun函数调用" << endl;
}
static void fun1() {
cout << "fun1函数调用" << endl;
}
};
int person::b = 10;
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
3.2このポインタの使い方
各非静的メンバー関数は1 つの関数インスタンスのみを作成します。これは、同じ型の複数のオブジェクトが 1 つのコードを共有することを意味します。そこで問題は、このコードはどのオブジェクトが自身を呼び出すかをどのように区別するかということです。
C++ は、特別なオブジェクト ポインターであるthis ポインターを提供することで、上記の問題を解決します。このポインタは、呼び出されたメンバー関数が属するオブジェクトを指します。
知らせ:
1.このポインタは、各非静的メンバ関数に暗黙的に含まれるポインタです。
2. このポインタは定義する必要はなく、直接使用できます。
このポインタの目的:
・仮パラメータとメンバ変数が同名の場合、thisポインタを使用することで同名の仮パラメータと変数を区別することができます。
·クラスの非静的メンバー関数でオブジェクト自体を返すには、return *this を使用します。
コード:
#include <iostream>
using namespace std;
class people {
public:
int age;
people(int age) {
this->age = age;
}
};
void zhixing() {
people p(10);
cout << p.age << endl;
}
int main() {
zhixing();
return 0;
}
自分自身を返すときは参照型を返すように注意し、共通の値型を返すときは戻り値は自分自身のコピーになります。
#include <iostream>
using namespace std;
class people {
public:
int age;
people(int age) {
this->age = age;
}
people& add(const people& p) {
this->age += p.age;
return *this;
}
};
void zhixing() {
people p1(10);
people p2(20);
p2.add(p1).add(p1).add(p1).add(p1);
cout << p2.age << endl;
}
int main() {
zhixing();
return 0;
}
4. メンバー関数への Null ポインター アクセス
C++ では、null ポインターもメンバー関数を呼び出すことができますが、this ポインターが使用されるかどうかにも注意する必要があります。
コード:
#include <iostream>
using namespace std;
class person {
public:
int age;
void fun1() {
cout << "fun1调用" << endl;
}
void fun2() {
cout << "fun2调用" << age << endl;
}
};
void diaoyong() {
person* p = NULL;
p->fun1();
p->age = 10;
p->fun2();
}
int main() {
diaoyong();
return 0;
}
現時点ではこれは null ポインターであり、これを含む呼び出しであるため、このポインターのない関数のみが正常に呼び出すことができます。
コード:
#include <iostream>
using namespace std;
class person {
public:
int age;
void fun1() {
cout << "fun1调用" << endl;
}
void fun2() {
if (this == NULL) {
return;
}
cout << "fun2调用" << age << endl;
}
};
void diaoyong() {
person* p = NULL;
p->fun1();
p->fun2();
}
int main() {
diaoyong();
return 0;
}
コードの堅牢性を高め、このポインタが null ポインタと判断された場合には関数から飛び出すようにします。
5. const 変更メンバー関数
定数関数:
1. メンバー関数に const を追加した後、この関数を定数関数と呼びます。
2. 定数関数内ではメンバ属性を変更できません。
3. member 属性を宣言するときにキーワードmutableを追加した後も、定数関数内で変更できます。
共通オブジェクト:
1. オブジェクトを宣言する前に const を追加して、それを定数オブジェクトと呼びます。
2. 定数オブジェクトは、定数関数とmutableで変更されたメンバー変数のみを呼び出すことができます。
5.1定数関数
このポインタの本質はポインタ定数であり、指すポインタは変更できませんが(person* const this)、このポインタが指すアドレスの値は変更できます。
定数関数 const は関数パラメータ リストの後に追加する必要があります。
コード:
#include <iostream>
using namespace std;
class person {
public:
int age;
void showage(int m) const{
// age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
};
void fun() {
person p;
p.age = 10;
p.showage(7);
}
int main() {
fun();
return 0;
}
このとき、コンパイラはエラーを報告し、関数内で age を変更することはできません。ただし、関数によって渡されるパラメーターは引き続き変更できます。
#include <iostream>
using namespace std;
class person {
public:
mutable int age;
void showage(int m) const{ //常函数
age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
};
void fun() {
person p;
p.age = 10;
p.showage(7);
}
int main() {
fun();
return 0;
}
メンバー属性を宣言するときにキーワード mutable を追加した後も、定数関数で変更できます。
5.2 定数オブジェクト
コード:
#include <iostream>
using namespace std;
class person {
public:
mutable int age;
void showage1(int m) const{
//age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
void showage2(int m) {
age = 89;
m = 100;
cout << "age=" << age << " m=" << m << endl;
}
};
void fun() {
const person p;
p.age = 10;
p.showage1(7);
//p.showage2(7); 报错
}
int main() {
fun();
return 0;
}
定数オブジェクトは、定数関数と mutable で変更されたメンバー変数のみを呼び出すことができます。通常の関数および通常のメンバー変数は呼び出せません
6. ヨウユアン
友達キーワード: 友達
フレンドの 3 つの実装:
1. グローバルは友達として機能する
2. クラスで友達ができる
3. メンバー機能はフレンドとして機能します
6.1 グローバルは友達として機能する
コード:
#include <iostream>
using namespace std;
class home {
friend void func(home& p);
public:
home(string keting, string woshi, string cuosuo):keting(keting),woshi(woshi),cuosuo(cuosuo) {
}
string keting;
private:
string woshi;
protected:
string cuosuo;
};
void func(home &p) {
cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
}
void fun() {
home p("客厅", "卧室", "厕所");
func(p);
}
int main() {
fun();
//cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
//保护和私有属性的不能访问
return 0;
}
要素関数はクラスのメンバー関数ではありませんが、クラスのすべてのメンバー変数を呼び出す権限を持っています。
6.2 カテゴリ 友情
#include <iostream>
using namespace std;
class building {
friend class goodgay; //声明友元类
public:
building();
string keting;
private:
string cesuo;
protected:
string woshi;
};
building::building() {
keting = "客厅";
cesuo = "厕所";
woshi = "卧室";
}
class goodgay {
public:
goodgay();
void show();
private:
building* p;
};
void goodgay::show() {
cout << this->p->keting << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
}
goodgay::goodgay() {
p = new building;
}
void f() {
goodgay a;
a.show();
}
int main() {
f();
return 0;
}
クラスがフレンドの場合、クラス内のすべてのメンバー関数は、フレンド クラス内のすべてのメンバーにアクセスできます。
6.3 メンバーはフレンドとして機能します
コード:
#include <iostream>
using namespace std;
class building;
class goodgay {
public:
goodgay();
void show1(building& p);
private:
building* p;
};
class building {
friend void goodgay::show1(building& p); //声明友元类
public:
building();
string keting;
private:
string cesuo;
protected:
string woshi;
};
building::building() {
keting = "客厅";
cesuo = "厕所";
woshi = "卧室";
}
void goodgay::show1(building& p1) {
cout <<p1.keting << ' ' << p1.cesuo << ' ' << p1.woshi << endl;
}
//void goodgay::show2() {
// cout << this->p->ketipng << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
//}
//无权限
goodgay::goodgay() {
p = new building;
}
void f() {
goodgay a;
building b;
a.show1(b);
}
int main() {
f();
return 0;
}
エラーを防ぐために、クラスを最初に宣言する必要があることに注意してください。グローバル関数のフレンドとは異なり、スコープを追加する必要があります。