类的构造函数(Constructor)和析构函数(Destructor)
- 构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会反回任何类型,也不会反回void。
 
- 析构函数也是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。函数名称与类的名称完全相同,只是在前面加了个
~波浪线作为前缀,它不会返回任何值,也不能带有任何参数。 
1.构造函数(Constructor)
  当我们定义一个类的对象时,系统就会自动调用它,进行专门的初始化对象用。如果我们没有定义构造函数,系统会默认生成一个默认形式,隐藏着的构造函数,这个构造函数的函数体是空的,它不具有任何功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
   | #include<iostream> #include<Cstring> using namespace std;
  class Student { 	private: 	int num; 	char name[100]; 	int score; 	public: 	Student(int n,char *str,int s); 	int print(); 	int Set(int n,char *str,int s); };
  Student::Student(int n,char *str,int s) { 	num=n; 	strcpy(name,str); 	score=s; 	cout<<"Constructor"<<endl; }
  int Student::print() { 	cout<<num<<" "<<name<<" "<<score; 	return 0; }
  int Student::Set(int n,char *str,int s) { 	num=n; 	strcpy(name,str); 	score=s; }
  int main() { 	Student A(1700710135,"yeshan",99); 	A.print();
  	 	cout<<endl;
  	Student B(1700710134,"xu jie",100); 	B.print(); 	return 0; }
   | 
 

由于在程序中定义了一个带默认参数的构造函数,则系统不会再自动生成,这个时候定义对象时也要传入三个默认初始值,因为构造函数可以重载,可以有多个兄弟,系统会找最匹配的一个函数
2.析构函数(Destructor)
 对象销毁时自动调用的一个函数,析构函数不能重载,一个类只能有一个析构函数,析构函数有助于跳出程序前释放内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
   | #include<iostream> #include<Cstring> using namespace std; class Student { 	private: 	int num; 	char name[100]; 	int score; 	public: 	Student(int n,char *str,int s); 	~Student(); 	int print(); 	int Set(int n,char *str,int s); };
  Student::Student(int n,char *str,int s) { 	num=n; 	strcpy(name,str); 	score=s; 	cout<<num<<" "<<name<<" "<<score<<" "; 	cout<<"Constructor"<<endl; }
  Student::~Student() { 	cout<<num<<" "<<name<<" "<<score<<" "; 	cout<<"destructor"<<endl; }
  int Student::print() { 	cout<<num<<" "<<name<<" "<<score<<endl; 	return 0; }
  int Student::Set(int n,char *str,int s) { 	num=n; 	strcpy(name,str); 	score=s; } int main() { 	Student A(100,"dot",11); 	Student B(101,"cpp",12); 	return 0; }
   | 
 

对象A和B的构造函数的调用顺序以及构造函数的调用顺序,完全相反!原因在于A和B对象同属局部对象,也在栈区存储,也遵循“先进后出”的顺序!
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。
它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。
当定义一个新对象并用同一个类型的对象对它进行初始化时,将显示使用拷贝构造函。
只包含类类型成员或内置类型(但不是指针类型)成员的类,无须显式地定义拷贝构造函数也可以拷贝。
显示定义拷贝构造函数的情况:
类有数据成员是指针;
有成员表示在构造函数中分配的其他资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
   | #include<iostream> using namespace std;
  class Age { 	public: 		int GetAge(void); 		Age(int age);            		Age(const Age& A);       		~Age();                  	private: 		int *ptr; };
  Age::Age(int age) { 	cout<<"调用构造函数"<<endl; 	ptr = new int; 	*ptr = age; }
  Age::Age(const Age& A) { 	cout<<"调用拷贝构造函数,并为指针ptr分配内存"<<endl; 	ptr = new int;
  	*ptr = *A.ptr;    }
  Age::~Age() { 	cout<<"释放内存"<<endl; 	delete ptr; }
  int Age::GetAge(void) { 	return *ptr; }
  void print_age(Age A) { 	cout<<"the age: "<<A.GetAge()<<endl;  } int main() { 	Age member_1(10);
  	Age member_2(member_2);
  	return 0; }
   | 
 





成员变量中加一个了指针成员,初始化中需要动态开辟内存,如果不自定义拷贝构造函数,而是用默认生成的,则会出现极大的安全隐患。
默认的拷贝构造函数仅仅是进行数值赋值,并不能为指针开辟内存空间。相当于代码This->str=str.本质上也就是两个指针指向了一块堆空间。程序结束回收对象的时候,会调用自己的析构函数,释放这块内存空间,由于两个对象要调用两次,即delete两次,就会出现错误
[引自](http://www.dotcpp.com/course/cpp/200020.html)
C++中的this指针
对象中隐藏的指针
- 每一个对象都能通过this指针来访问自己的地址。this指针是所有成员函数额隐含参数。因此在成员函数内部,它可以用来指向调用的对象。
 
- 如果程序中有多个属于同一类的对象,因成员函数的代码仅有一份,所以为了区分它们是哪个对象调用的成员函数,编译器也是转化成this->成员函数这种形式来使用的。
 
- 友元函数没有this指针,因为友元不是类的成员。只有成员函数才有this指针。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   | #include<iostream> using namespace std;
  class Age {     public: 	    Age(int your_age=18)   		{ 			cout<<"Constructor now"<<endl; 			age=your_age; 		} 		int GetAge() 		{ 			return age; 		} 		int compare(Age member) 		{ 			return this->GetAge()>member.GetAge();    		} 	private: 	    int age; };
  int main() { 	Age member_1(20),member_2(24);
  	if(member_1.compare(member_2)) 	{ 		cout<<"member_1 is older than member_2"<<endl; 	} 	else 	{ 		cout<<"member_1 is younger than member_2"<<endl; 	} }
   | 
 

关键字new和delete
- new(新建)用于新建一个对象。new 运算符总是返回一个指针。由 new 创建。
 
- delete(删除)释放程序动态申请的内存空间。delete 后面通常是一个指针或者数组 [],并且只能 delete 通过 new 关键字申请的指针。