一.类对象作为类成员
类可以作为另一个类的成员
代码:
#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的时候正好相反,外部类先析构,内部类再析构。
二.静态成员
静态成员就是在成员变量前面加上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;
}
同样,静态成员函数也是可以通过类名来调用,需要注意静态成员函数只能调用静态成员变量。
三.this指针
3.1成员变量和函数的存储
在C++中,类内的的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上
在C++中, 空类也占用一个字节。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.2this指针使用
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码那么问题是:这一块代码是如何区分那个对象调用自己的呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象
注意:
1.this指针是隐含每一个非静态成员函教内的一种指针
2.this指针不需要定义,直接使用即可
this指针的用途:
·当形参和成员变量同名时,可用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;
}
四.空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到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;
}
只能成功调用没有this指针的函数,因为此时this是空指针,含有this的调用
代码:
#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;
}
增加代码的健壮性,判断this指针是空指针的时候,跳出函数。
五.const修饰成员函数
常函数:
1.成员函数后加const后我们称为这个函数为常函数。
2.常函数内不可以修改成员属性。
3.成员属性声明时加关键字mutable后,在常函数中依然可以修改。
常对象:
1.声明对象前加const称对象为常对象。
2.常对象只能调用常函数和用mutable修饰的成员变量。
5.1常函数
this指针本质是指针常量,指针的指向是不可以修改的(person* const this),但是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修饰的成员变量。普通函数和普通成员变量不能调用
六.友元
友元关键字:friend
友元的三种实现:
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;
}
注意类要先声明一下,防止报错,与全局函数做友元不同的是,要加上作用域。