C++知识梳理-类与对象-对象特征
一 构造函数与析函数
进行初始化操作,每个类中都是默认存在的。如果我们自己不构造,那么编译器会进行空实现
1 构造函数
1.1 语法:与类同名 无返回值且不用写void 可以含有参数且可以重载 只调用一次
class Person { Person() { cout<<"默认构造函数调用"<<endl; } };1.2 分类:默认构造函数,有参构造函数,拷贝构造函数
class Person { //默认构造函数 Person() { cout<<"默认构造函数调用"<<endl; } //有参数构造函数 Person(int a) { cout<<"有参构造函数调用"<<endl; } //拷贝构造函数 Person(const Person &p) { cout<<"拷贝构造函数调用"<<endl; } };1.3 调用方式:括弧法,显示法,隐式转移法
//1 括弧法 void test01() { Person p1;//调用默认构造函数 Person p2(10);//调用有参构造函数 Person p3(p1);//调用拷贝构造函数 } //2 显示法 void test02() { Person p1;//调用默认构造函数 Person p2 = Person(10);//调用有参构造函数 Person p3 = Person(p1);//调用拷贝构造函数 } //3 隐式转换法 void test03() { Person p1;//调用默认构造函数 Person p2 = 10;//调用有参构造函数 Person p3 = p1;//调用拷贝构造函数 }2 析函数
2.1 语法:与类同名前面加~ 不可以有参数且不可以重载 没有返回值且不用写void
class Person { ~Person() { cout<<"默认析函数调用"<<endl; } };注意事项:关于两者的调用test01()中的Person p1是存放在栈上面的的,函数运行之后立马释放,所以会立刻返回析函数,但是在主函数上的则不同,需要等到整个函数运行完才会输出析函数。
int main() { test01(); Person p; cout<<"随便什么"<<endl; system("pause"); return 0; }二 拷贝函数调用时机
一共以下三种情况:1. 使用一个已经创造完毕的对象来初始化一个新对象 2.值传递的方式给函数参数传值 3.值方式返回局部对象
1 使用一个已经创造完毕的对象来初始化一个新对象
class Person { public: Person() { cout << "默认构造函数调用" << endl; } Person(int a) { ID = a; cout << "有参构造函数调用" << endl; } //拷贝构造 Person(const Person& p) { //将传入的所有属性,拷贝到我身上 ID = p.ID; cout << "Person 拷贝构造函数的调用" << endl; } ~Person() { cout << "Person 解析函数的调用" << endl; } int ID; }; void test01() { Person p1(123); Person p2(p1); }2 值传递的方式给函数参数传值
void function(Person p) { } void test02() { Person p1; function(p1); } //输出结果如下 //默认构造函数调用 //拷贝构造函数调用 //解析函数的调用 //解析函数的调用 //说明拷贝了一份到参数Person p中,相当于Person p(p1)3 值方式返回局部对象
Person function02() { Person p1; cout << (int*)&p1 << endl; return p1; } void test03() { Person p = function02(); cout << (int*)&p << endl;//输出p的存放地址10进制 }三 构造函数调用规则
C++会给每一个类添加至少三个函数:默认构造(空实现),拷贝构造(空实现),析函数(值拷贝)。
注意事项:
1 如果定义了有参构造函数,C++不会提供默认无参构造函数,但是会提供默认拷贝构造
2 如果定义了拷贝函数,C++不会提供其他构造函数
四 深拷贝与浅拷贝
浅拷贝:原来类有什么,我就拷贝什么,之作内容上的拷贝
//浅拷贝 class Person { public: Person() { cout << "默认构造函数调用" << endl; } Person(int a, int m_Weight) { age = a; Weight = new int(m_v); cout << "有参构造函数调用" << endl; } Person(const Person &p) { cout << "浅拷贝构造函数调用" << endl; age = p.age; Weight = p.Weight;//编译器默认实现的是这行代码,还是沿用了之前的指针,所以到了最后释 //放的时候会显示重复释放内存 } ~Person() { //将堆区开辟数据做释放操作 if (Height != NULL) { delete Height; Height = NULL; } cout << "解析函数调用" << endl; } int ID; int* Weight; };深拷贝
class Person { public: Person() { cout << "默认构造函数调用" << endl; } Person(int a, int m_Weight) { age = a; Weight = new int(m_v); cout << "有参构造函数调用" << endl; } Person(const Person &p) { cout << "深拷贝构造函数调用" << endl; age = p.age; Weight = new int(*p.Height); //解引用之后重新开辟新的位置存放新指针 } ~Person() { //将堆区开辟数据做释放操作 if (Height != NULL) { delete Height; Height = NULL; } cout << "解析函数调用" << endl; } int ID; int* Weight; };五 初始化列表
传统初始化方式
class Person { public: //传统初始化 Person(int a,int b,int c) { m_a = a; m_b = b; m_c = c; cout << "默认构造函数调用" << endl; } Person(int a, int b, int c) :m_a(a), m_b(b), m_c(c) { } ~Person() { cout << "解析函数调用" << endl; } int m_a; int m_b; int m_c; }; void test01() { Person p1(18, 160,10); cout << "a:" << p.m_a << "b:" << p.m_b << "c:" << p.m_c << endl; }新的初始化列表方式
class Person { public: Person(int a, int b, int c) :m_a(a), m_b(b), m_c(c) { } int m_a; int m_b; int m_c; }; void test01() { Person p(1,2,3); cout << "a:" << p.m_a << "b:" << p.m_b << "c:" << p.m_c << endl; }六 类对象作为成员
一个类可以作为另一个类的成员,这和结构体的知识点是一致的。
class Car { public: Car(string Cname) { m_Cname = Cname; } string m_Cname; }; class Person { public: //相当于 Car C = b 相当于隐式转换法 Person(string a, string b) :name(a), P(b) { } Car c; string name; }; void test01() { Person p1("张三", "宝马"); cout << p1.name <<"开着一个"<<p1.P.m_Cname<<"汽车"<<endl; }七 静态成员
1 静态成员-变量
性质:1所用对象共用一份数据2 编译阶段就分配了内存 3类内声明类外初始化操作
class Person { public: //静态成员变量 static int m_A; //静态成员变量也是有访问权限的 private: static int m_B; }; int Person::m_A = 100;//类外初始化操作 int Person::m_B = 200; void test01() { Person p; cout << p.m_A << endl; Person p2; p2.m_A = 200; cout << p.m_A << endl;//所有共享一份数据,输出为200 }访问方法有以下两种
void test02() { //静态成员变量 不属于某个对象上,所有对象都共享给一份数据 //因此静态成员变量有两种访问方式 //1 通过对象进行访问 Person p; cout << p.m_A << endl; //2 通过类名进行访问 cout << Person::m_A << endl; //cout << Person::m_B << endl; 类外访问不到私有静态成员 }2 静态成员-函数
性质:1 所有对象共享同一个函数 2 静态成员函数只能访问静态成员变量
class Person { public: static void function01() { m_A = 100;//静态成员函数可以访问 静态成员变量 m_B = 100;//静态成员函数不可以访问 非静态成员变量 因为无法区分到底是哪个对象上的m_B的属性 cout << "static void func调用" << endl; } static int m_A; int m_B; //也是有访问权限的 private: static void function02() { } };同样,调用方法也是两种
void test01() { //通过对象访问 Person p; p.function01(); //通过类名访问 Person::function01(); //Person::function02();类外访问不到私有静态函数 }