类对象作为类成员
汽车由各种零件,如轮胎,如发动机,其中这些零件又可以归属到零件类
所以我们可以说汽车类中包含了一个零件类
那么,问题来了:汽车类里包含了零件类,那么既然是类,就有构造函数和析构函数呀,谁的函数先实现呢?
我们先给出答案,后边代码验证
构造顺序:因此当其他类对象作为本类成员,构造时先构造类对象,再构造自身。
析构顺序:与构造相反
#include<iostream>
#include<string>
using namespace std;
//手机类
class Phone {
public:
Phone() {
}
Phone(string pName):m_Pname(pName) {
cout << "Phone的构造函数调用" << endl;
}
~Phone() {
cout << "Phone的析构函数的调用" << endl;
}
//手机名
string m_Pname;
};
class Person {
public:
Person(string name, string pName):m_Name(name),m_Phone(pName) {
cout << "Person的构造函数调用" << endl;
}
~Person() {
cout << "Person的析构函数的调用" << endl;
}
//姓名
string m_Name;
//手机
Phone m_Phone;
};
void test01() {
Person p("张三", "iphone");
cout << p.m_Name << "拿着: " << p.m_Phone.m_Pname << endl;
}
int main() {
test01();
return 0;
}
注意!!!在Person里,当我们底下创建Person p时候,传入的参数pName是string类型,而我们声明的pName是Phone类型的,Phone 是一个对象。若理解为值赋给m_Phone的话,就错误了,因为值的话,m_Phone是Phone类型。所以应该这样理解,此处就依赖我们讲过的隐式转换法,相当于 Phone m_Phone = pName,用了隐式转换法,而上边刚好有一个有参构造函数。
静态成员
定义:静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
静态成员变量不属于某个对象,因为所有对象都共享同一份数据如Person p,p1共享一个属性m_A。
分类:
分为两类:
静态成员变量
特点:
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
静态成员变量有两种访问方式:
1.通过对象进行访问
2.通过类名访问,如要喝一杯瑞幸,可以直接去附近分店做一杯,也可找到他总部做一杯
如:cout << Person::m_A << endl
静态成员变量也有访问权限
#include<iostream>
using namespace std;
class Person {
public:
static int m_A; //类内声明
private:
static int m_B;
};
int Person::m_B = 200;
int Person::m_A = 100;//类外初始化
void test01() {
Person p;
cout << p.m_A << endl;
Person p2;
p2.m_A = 200;
cout << p.m_A << endl; //此时共享数据已经被更改了
//cout << Person::m_B; //error,私有成员类外无法访问
}
int main() {
test01();
return 0;
}
静态成员函数
访问方式:通过对象访问、通过类名访问
特点
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量:因为如果可以访问普通成员变量的话,无法区分是更改哪个对象的成员变量,因为静态成员变量是所有对象共有的,不需要区分,而普通成员变量的话需要区分
#include<iostream> using namespace std; //静态成员函数: //所有成员共享同一个函数 //静态成员函数只能访问静态成员 //通过对象访问 //通过类名访问 class Person { public: static void func() { m_A = 100; //m_B = 200; //error,m_B为非静态成员,当使用Person::去调用函数时,编译器不知道应该修改哪个对象的m_B; //而m_A所有成员都公用,调用去修改时一改全改 //理解不了这种的话,就理解为静态成员编译前就初始化,然后就分配内存 cout << "static void func调用" << endl; } int m_B; static int m_A; private: static void func2() { cout << "static void func2调用" << endl; } }; int Person::m_A = 0; void test01() { Person p; p.func(); Person::func(); //Person::func2(); //error,类外无法访问私有静态成员函数 } int main() { test01(); return 0; }
this指针
在C++中,成员变量和成员函数是分开存储的,每一个非静态成员函数只会由一个实例,
每一个非静态成员函数只会诞生一份函数实例,所以会出现多个同类型对象共同使用这个函数,也就是共用一份代码,那么这一块代码如何区分哪个对象调用了它自己呢?
答案是用this指针。
this指针指向被调用的成员函数所属的对象
静态函数没this,因为他不需要指向,他不属于任何一个对象
this隐含在每一个非静态成员函数中,属于一种指针。
使用时机:
- 返回对象本身用*this
- 当形参和成员变量同名时,可用this指针来区分
使用方法:
- 1.在类的非静态成员函数中返回对象本身可使用 return *this;
- 当形参和成员变量同名时,可用this指针来区分(解决名称冲突)
- this指针本质,指针常量, 类似 Person* sonst this
#include<iostream>
using namespace std;
class Person {
public:
//解决名称冲突
Person(int age) {
//age = age; //error,目的是赋值,但是出现错误;
//可能所有age都被当成参数age了
this->age = age;
}
/*void PersonAdd(Person& p) {
this->age += p.age;
}*/
Person PersonAdd(Person& p) {
this->age += p.age;
return *this; //this为指向p2的一个指针,*解引用
}
int age;
};
void test01() {
Person p1(19);
cout << "p1的年龄为:" << p1.age << endl;
}
void test02() {
Person p1(10);
Person p2(20);
//2.若是函数返回没有&引用的话,此时第一次函数返回一个复制体p2·,然后再调用再生成一个复制体p2··,再一次p2···
//3.而我们最后输出的是p2
//4.有了引用的话,返回的是p2的别名
//5.这里这个p2···被p3接受
Person p3(10);
p3 = p2.PersonAdd(p1).PersonAdd(p1).PersonAdd(p1);
//1.此时想这样加好几次,但p2返回值为void,如果返回值为Person类型就可以调用这个函数
p2.PersonAdd(p1).PersonAdd(p1).PersonAdd(p1);
cout << p2.age << endl;
}
int main() {
test01();
test02();
return 0;
}
此处p2.PersonAdd(p1) .PersonAdd(p1) .PersonAdd(p1) ;为链式编程思想,仔细想想我们还在哪见过这种方法
在cin输出一个值时候我们是不是习惯在后边加一个endl,此时 cin << a << endl;就是一个链式编程。