类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数
// person.h #ifndef _PERSON_H_ #define _PERSON_H_ class Person{ public : Person(); Person(int myage, char *myname); Person(const Person &a); Person& operator=(const Person& other); ~Person(void); void set_age(int myage); int get_age(void) const; void set_other_age(Person &a, int b); void print() const; private: int age; char *name; }; #endif
// person.cc #include "person.h" #include <iostream> #include <stdio.h> #include <string.h> using namespace std; Person::Person():age(10), name(NULL) { //nothing cout<<"no param construct!"<<endl; } Person::Person(int myage, char *myname) { age = myage; if(myname != NULL){ name = new char[strlen(myname) + 1]; this->print(); strcpy(name, myname); } cout<<"param construct!"<<endl; } Person::Person(const Person &a) { cout <<"copy constructor!"<<endl; if(a.name != NULL){ name = new char[strlen(a.name)+1]; this->print(); strcpy(name, a.name); age = a.age; } else { name = NULL; age = 10; } } Person& Person::operator=(const Person &a) { cout <<"= constructor!"<<endl; if(&a == this){ return *this; } if(name != NULL){ delete [] name; name = NULL; } if(a.name != NULL){ name = new char[strlen(a.name)+1]; this->print(); strcpy(name, a.name); age = a.age; } else { name = NULL; age = 10; } return *this; } Person::~Person() { if(NULL != name){ delete [] name; name = NULL; } cout<<"destructor!"<<endl; } void Person::set_age(int myage) { age = myage; } int Person::get_age(void) const { return age; } void Person::set_other_age(Person& a, int b) { a.age = b; //a.set_age(b); } void Person::print() const { if(name != NULL) cout <<"value:" << name; cout<< " name=" << static_cast<void*> (name) << endl; }
// main.cc #include "person.h" #include <iostream> using namespace std; int main(int argc, char *argv[]) { Person a(11, "xiaohhhhh"); Person b(13, "mingttttt"); Person m; m = b; a.print(); b.print(); m.print(); Person n(13, "qing"); b=n; a=n; m=n; a.print(); b.print(); m.print(); return 0; }
构造函数、析构函数和赋值函数是类最重要的函数,被称为The Big Three。
与其他成员函数相比,The big three特殊之处在于,如果代码中没有提供这些函数的实现,C++编译器自动合成缺省的函数实现。
有指针成员变量的类一定要提供The Big Three的实现,即使没有指针变量,作为良好的编程习惯也应该提供The Big Three的实现。
1. 构造函数
和类同名,无返回值,用来初始化类的对象。
构造函数可重载。
编译器提供默认无参构造函数,若声明新的,则采用新的构造函数。一般多应创建一个无参的构造函数,因为创建了有参构造函数后,默认的无参构造函数被覆盖。
构造函数在对象创建后马上调用。
Person a; //调用无参构造函数
Person a(20, "Xiaoming"); //调用两参构造函数
Person(int age=0, const char *name = NULL);构造函数,相当于创建无参或两参构造函数。
2.拷贝构造函数
Person(const Person &a);
如果没有提供拷贝构造函数,编译器会默认提供一个(执行逐个成员初始化,将新对象初始化为原对象的副本,这里的逐个是指编译器将现有对象的每个非static成员,依次复制到正在创建的对象)。
如果类有指针成员变量或类数据成员管理资源(如打开一个文件),默认构造函数并不会自动分配指针所指向的空间(默认构造函数仅提供浅拷贝),需要添加拷贝构造函数实现深拷贝。
默认拷贝构造函数实现浅拷贝:指针成员变量指向同一存储区域,而不是重新分配区域再赋值(深拷贝)。
如果想禁止一个类的拷贝构造,需要将拷贝构造函数声明为private。
3. 析构函数
析构函数不可重载。
类名前加~的函数,无参数,无返回值。
先调用析构函数->后销毁对象。
默认的析构函数不会释放指针成员变量分配的内存区域,可能造成内存泄露。有指针成员变量时必须实现析构函数。
4. 赋值函数
Person& operator=(const Person& other);
基本与拷贝构造等价。如果想禁止一个类的赋值函数,需要将拷贝构造函数声明为private。
Person b=a; //拷贝构造函数
Person b;
b = a; //赋值函数 operator=
5. 构造函数的初始化列表
const变量必须用初始化列表进行初始化。
Person():age(10), name(NULL)中":age(10),name(NULL)"为初始化列表。
6. set_other_age()同一类的不同对象可以访问其他对象的私有数据。
7. this指针
每个成员方法都包含一个隐藏参数this,this是一个对象的指针,指向调用函数的对象。
判断自赋值:
if(this == &a){ return *this; }