构造、析构、拷贝构造、赋值运算符重载、取地址操作符重载、const修饰的取地址操作符重载
(1).构造函数:为对象分配空间、进行初始化(初始化列表、构造函数函数体内赋值)
class Date { public: Date() { _iYear=2016; _iMonth=1; _iDay=1; } Date(const int Year=1990,const int Month=1,const int Day=1) { _iYear=Year; _iMonth=Month; _iDay=Day; } public: int _iYear; int _iMonth; int _iDay; }; ***全缺省的构造函数和无参的构造函数只能有一个,否则调用的时候就会产生冲突
(2).析构函数:
特点:无参数无返回值(但有this指针)
class Date { public: Date() { _iYear=2016; _iMonth=1; _iDay=1; cout<<"this:"<<this<<endl; } //Date(const int Year=1990,const int Month=1,const int Day=1) //{ // _iYear=Year; // _iMonth=Month; // _iDay=Day; //} ~Date() { cout<<"this:"<<this<<endl; } public: int _iYear; int _iMonth; int _iDay; }; int main() { Date d,d1,d2,d3,d4; return 0; }
*** 对象生命周期结束后,后构造的对象先释放
(3).拷贝构造:用已有对象创建一个新的对象
***浅拷贝:只是值的拷贝的拷贝方式
class Person { public: Person(char* name,int age) { m_name=(char*)malloc(sizeof(char)*10); if(NULL==m_name) { cout<<"out of memort"<<endl; exit(1); } strcpy(m_name,name); m_age=age; } ~Person() { free(m_name); m_name=NULL; } private: char* m_name; int m_age; }; int main() { Person p1("zhang",20); Person p2(p1); return 0; } ***p1 p2指向同一块内存空间;析构的时候p2的this先释放了这段空间,p1就成为野指针,程序会出现bug
***深拷贝:为对象重新分配空间,然后将值拷贝
Person(const Person &p) { m_name=new char[strlen(p.m_name)+1]; if(NULL!=m_name) { strcpy(m_name,p.m_name); m_age=p.m_age; } }
(4).赋值运算符的重载:它是两个已有对象一个给另一个赋值的过程
默认的赋值运算符重载函数实现的是数据成员的逐一赋值的方法,是一种浅拷贝
***浅拷贝会导致指针悬挂的问题:
class Person { public: Person(char* name,int age) { m_name=(char*)malloc(sizeof(char)*10); if(NULL==m_name) { cout<<"out of memort"<<endl; exit(1); } strcpy(m_name,name); m_age=age; } ~Person() { free(m_name); m_name=NULL; cout<<this<<endl; } private: char* m_name; int m_age; }; int main() { Person p1("zhang",20); Person p2("xiao",10); p2=p1; return 0; } p2=p1;两个对象的this指向同一块空间;p2析构后,p1的指针就形成悬挂
***通过深层拷贝解决指针悬挂的问题:
Person& operator=(const Person &p) { if(this==&p) return *this; delete[]m_name; m_name=new char[strlen(p.m_name)+1]; strcpy(m_name,p.m_name); m_age=p.m_age; return *this; }
***const成员函数可以访问非const对象的非const数据成员、const数据成员、也可以访问const对象内的所有数据成员
***非const成员函数可以访问非const对象的非const数据成员、const数据成员、但不可以访问const对象的任意数据成员
***作为一种良好的变成风格,在生命一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能的将该数据成员声明为const成员函数