欢迎来观看温柔了岁月.c的博客
目前
设有C++学习专栏
C语言项目专栏
数据结构与算法专栏
目前主要更新C++学习专栏,C语言项目专栏不定时更新
待C++专栏完毕,会陆续更新C++项目专栏和数据结构与算法专栏
一周主要三更,星期三,星期五,星期天,
感谢大家的支持
构造函数
特点
1.名字和类名相同
2.没有返回值
3.构造函数是用来构造对象,构造对象时候,必定调用构造函数
4.不写构造函数,存在一个默认的构造函数,默认的构造函数是无参的,所以可以构造无参对象
5.默认的构造函数可以删掉,通过delete可以删除默认的构造函数
6.显示使用默认的构造函数,用defalt做显示调用
7.通常构造函数是public
8.如果自己写了构造函数,系统的默认构造函数就会不存在
9.构造函数决定对象的长相(构造函数有几个参数,构造的对象就要有几个参数)
10.构造函数通常做的事情,就是给数据成员初始化。
11.构造函数也是函数,可以进行重载,也可以进行缺省。
12.通过缺省和重载,可以创建各种彰显不同的对象
#include<iostream> #include<string> using namespace std; class MM { public: MM() = default; //显示使用默认构造函数 MM() = delete; //删除默认的构造函数 private: int age; string name; }; int main() { system("pause"); return 0; }
注意:如果一个类中的默认构造函数被删除的话,是不能够构造对象的。
构造函数的创建和使用
有参构造函数
#include<iostream> #include<string> using namespace std; class MM { public: MM(int m_age, string m_name) { age = m_age; name = m_name; } void printDate() { cout << age << "\t" << name << endl; } private: int age; string name; }; int main() { MM mm(10, "温柔了岁月"); //构造函数有2个参数,所以这路必须也要有两个参数,创建对象的过程就是调用构造函数过程 mm.printDate(); system("pause"); return 0; }
无参构造函数
#include<iostream> #include<string> using namespace std; class MM { public: MM(); //无参构造函数 private: int age; string name; }; int main() { MM mm; system("pause"); return 0;
关于new的构造函数
#include<iostream> #include<string> using namespace std; class MM { public: MM(); //无参构造函数 MM(int m_age, string m_name) { age = m_age; name = m_name; } private: int age; string name; }; int main() { MM *p1 = new MM; //无参构造函数 MM* p2 = new MM(18, "温柔了岁月"); //有参的构造函数 system("pause"); return 0; }
析构函数
特点
1.~类名,当作析构函数的名称
2.没有参数
3.释放数据成员new的内存
在对象死亡前,自动调用
4.如果数据成员没有做new的操作,可以不写析构函数,不写析构函数,系统存在一个默认的析构函数
//析构函数 #include<iostream> #include<cstring> using namespace std; class MM { public: MM(const char * str) { int length = strlen(str) + 1; name = new char[length]; strcpy(name, str); } ~MM() { if (name != nullptr) { delete name; name = nullptr; } cout << "析构函数" << endl; } private: char* name; }; int main() { MM* pmm = new MM("温柔了岁月"); delete pmm; pmm = nullptr; //立刻调用析构函数 system("pause"); return 0; }
拷贝构造函数
特点
1.拷贝构造函数也是构造函数
2.拷贝构造函数的参数是固定的:对对象的引用
3.拷贝构造函数不写,会存在一个默认的拷贝构造函数
4.拷贝构造函数的作用:通过一个对象,创造另一个对象。
#include<iostream> #include<string> using namespace std; class MM { public: MM(int m_age) { age = m_age; } //拷贝构造函数,通过传入对象属性,确定创建对象属性 MM(MM& object) { age = object.age; } void printDate() { cout << age << endl; } private: int age; }; //函数传参也可以隐式调用 void print(MM object) { object.printDate(); } void Print(MM& object) //引用只是取别名,不调用拷贝构造函数,效率较高 { object.printDate(); } int main() { MM mm(10); //产生对象 MM pmm = mm; //隐式构造 MM pm(mm); //显式构造 print(mm); //隐式调用拷贝构造函数 system("pause"); return 0; }
深拷贝和浅拷贝
浅拷贝:
没有在拷贝构造函数中,使用new
默认的拷贝构造函数都是浅拷贝
深拷贝:
在拷贝构造函数中做了new的操作
内存释放问题:
浅拷贝会导致同一段内存重复释放
//浅拷贝问题
#include<iostream> #include<cstring> using namespace std; class MM { public: MM(const char* m_name) { name = new char[strlen(m_name) + 1]; strcpy(name, m_name); } MM(MM& object) { name = object.name; } ~MM() { if (name != nullptr) { delete name; name = nullptr; } } private: char* name; }; int main() { MM mm("温柔了岁月"); MM pmm = mm; return 0; }
delete把相同的两端数据都删除了,所以程序中断,浅拷贝的问题,要用深拷贝来解决。
解决方法
#include<iostream> #include<cstring> using namespace std; class MM { public: MM(const char* m_name) { name = new char[strlen(m_name) + 1]; strcpy(name, m_name); } MM(MM& object) { int length = strlen(object.name) + 1; name = new char[length]; strcpy(name, object.name); } ~MM() { if (name != nullptr) { delete name; name = nullptr; } } private: char* name; }; int main() { MM mm("温柔了岁月"); MM pmm = mm; return 0; }
一旦类中有指针,做了内存申请,并且对对象做了拷贝操作,就必须使用深拷贝
匿名对象
1.匿名对象就是无名对象,匿名对象只能充当右值,
2.如果做特殊处理,会直接死掉,要想对匿名对象赋初值,必须存在移动构造拷贝或者有const存在的普通拷贝构造。
#include<iostream> using namespace std; class MM { public: MM(int m_age) { age = m_age; } void printDate() { cout << age << endl; } MM(MM&& object) { age = object.age; cout << "调用移动构造" << age << endl; } ~MM() { cout << "析构函数" << endl; } private: int age; }; int main() { MM(10); //匿名对象没有名字 MM girl = MM(10); //赋值对象, girl接管匿名对象的所有权 girl.printDate(); system("pasuse"); return 0; }
析构与构造调用的顺序
1 . 一般情况,构造顺序和析构顺序是相反的
2.全局和静态变量,最后释放的
3.delete会立刻调用析构函数