鸡啄米:C++编程之十四学习之构造函数和析构函数
1. 本人学习鸡啄米课程的笔记记录,用来记录学习的历程和进度
2. 构造函数
我们在声明一个变量时,如果对它进行了初始化,那么在为此变量分配内存空间时还会向内存单元中写入变量的初始化。声明对象有相似的过程,程序执行时遇到对象声明语句时会向操作系统申请一定的内存空间来存放这个对象,但是它能像一般变量那样初始化时写入指定的初始值吗?类的对象太复杂了,要实现这一点不太容易,这就需要构造函数来实现。
构造函数的作用就是在对象被创建时利用特定的初始值构造对象,把对象置于某一个初始状态,它在对象被创建的时候由系统自动调用,我们只需要使用默认的构造函数或者自己定义构造函数,而不用管怎么调用的。
构造函数也是类的成员函数,除了有成员函数的所有特征外,还有一些不同之处:构造函数的函数名跟类名一样,而且没有返回值。构造函数一般被声明为公有函数,除非我们不允许某个类生成对象则将它声明为private或protected属性。编译器碰到对象声明语句时,会自动生成对构造函数的调用语句,所以我们常说构造函数是在对象声明时由系统自动调用的。
如果没有定义类的构造函数,编译器编译时会自动生成一个默认形式的构造函数,这个构造函数不做任何事,那么为什么还要生成它呢?因为C++在对象建立时都会调用构造函数,所以如果没有自己定义构造函数,那么即使是什么都不做的构造函数也是要有的。
3. 现在在Clock类中加入自己定义的构造函数:
1 class Clock 2 { 3 public: 4 Clock(int NewH, int NewM, int NewS); //构造函数 5 void SetTime(int NewH, int NewM, int NewS); 6 void ShowTime(); 7 private: 8 int Hour, Minute, Second; 9 };
4. 构造函数的实现
1 Clock::Clock(int NewH, int NewM, int NewS) 2 { 3 Hour=NewH; 4 Minute=NewM; 5 Second=NewS; 6 }
5. main函数调用
1 int main() 2 { 3 Clock c(0,0,0); //隐含调用构造函数,将初始值作为实参。 4 c.ShowTime(); 5 return 0; 6 }
6. 拷贝构造函数
我们可以将一个变量的值赋给另一个同类型的变量,那么可以将一个对象的内容拷贝给相同类的另一个对象吗?可以,我们可以将第一个对象的数据变量的值分别赋给另一个对象的数据变量,但是,如果数据变量数很多的话那将是很麻烦的,这时候我们就需要有拷贝构造函数。
拷贝构造函数是一种特殊的构造函数,因为它也是用来构造对象的。它具有构造函数的所有特性。拷贝构造函数的作用是用一个已经存在的对象去初始化另一个对象,这两个对象的类类型应该是一样的。定义拷贝构造函数的形式是:
1 class 类名 2 { 3 public : 4 类名(形参); //构造函数 5 类名(类名 &对象名); //拷贝构造函数 6 ... 7 }; 8 类名::类(类名 &对象名) //拷贝构造函数的实现 9 { 10 函数体 11 }
7. 举例说明拷贝构造函数
1 class Point 2 { 3 public: 4 Point(int xx=0,int yy=0) {X=xx; Y=yy;} 5 Point(Point &p); 6 int GetX() {return X;} 7 int GetY() {return Y;} 8 private: 9 int X, Y; 10 };
8. 构造函数的具体实现
1 Point::Point(Point &p) 2 { 3 X=p.X; 4 Y=p.Y; 5 cout<<"拷贝构造函数被调用"<<endl; 6 }
9.析构函数
自然万物都是有生有灭的,类的对象也一样是有生命周期的,一样会消亡。鸡啄米给大家讲一种情况:如果在函数中声明了一个对象,那么在这个函数运行完返回调用函数时,声明的对象也会释放,就像上面说的fun2函数中对象A那样。
在对象释放时都有什么工作要做呢?我们经常遇到的情况就是:构造函数时动态申请了一些内存单元,在对象释放时就要同时释放这些内存单元。动态分配内存的知识后面鸡啄米会讲。
析构函数和构造函数的作用是相反的,它会在对象被删除之前做一些清理工作。析构函数是在对象要被删除时由系统自动调用的,它执行完后对象就消失了,分配的内存空间也释放了。
析构函数是类的一个公有函数成员,它的名称是在类名前加“~”形成,不能有返回值,大家注意下,它和构造函数不同的是它不能有任何形参。如果没有定义析构函数系统也会自动生成一个默认析构函数,默认析构函数也不会做任何工作。一般如果我们想在对象被删除之前做什么工作就可以把它写到析构函数里。
10. 析构函数举例
1 class Point 2 { 3 public: 4 Point(int xx, int yy); 5 ~Point(); 6 //...其他函数原型 7 private: 8 int X, int Y; 9 char *p; 10 };
11. 析构函数具体实现
Point::Point(int xx,int yy) { X=xx; Y=yy; p=new char[20]; // 构造函数中动态分配char型内存 } Point::~Point() { delete []char; // 在类析构时释放之前动态分配的内存 }