1.构造函数
构造函数是一种特殊的函数,它在对象被创建时被调用,与类同名无返回类型,可以被重载。构造函数的可以在类内实现也可以在类外实现。
构造函数的声明类似于下面的代码:
class Human { public: Human();//构造函数声明 };
构造函数在类声明中实现类似于下面的代码:
class Human { public: Human () { //构造函数的实现部分 } };
构造函数在类的声明外实现类似于下面的代码:
class Human { public: Human (); }; Human::Human() { //构造函数的实现部分 };
使用构造函数便于我们对类内的属性进行初始化,确保已知属性中不包含随机值。构造函数也是可以重载的,这说明在调用构造函数时有时是需要提供参数的,可以在不提供参数的情况下调用的构造函数
称作默认构造函数。在调用构造函数初始化对象的属性时,又需要提供不同的参数,这时重载构造函数就可以为我们提供帮助。
构造函数的重载类似于下面的代码:
class Human { private: string Name; int Age; public: Human (int HumanAge) { Age=HuanAge; } Human (string HumanName,int HumanAge) { Name=HumanName; Age=HumanAge; } };
其实构造函数不仅可以重载,其参数还可以带有默认值。
例如下面这样:
class Human { private: string Name; int Age; public: Human (int HumanAge) { Age=HuanAge; } Human (string HumanName,int HumanAge=22)//与上一段代码的区别在于给出了HumanAge的默认值 { Name=HumanName; Age=HumanAge; } /*Human (int HumanAge,string HumanName="Tom")//去掉多行注释符号后,这种重载会报错,原因在于当提供一个int型的参数调用构造函数时,系统并不知道该调用Human(int)Human(int,string HumanName="Tom") { Name=HumanName; Age=HumanAge; }*/ };
2.析构函数
与析构函数一样,析构函数也看上去和类同名,只是在函数名前多了波浪号"~"。每当对象不再在作用域内或通过delete被删除,进而被销毁时都将调用析构函数。这使得析构函数是重置变量以及释放动态分配的内存和其他资源的理想场所。析构函数不能够重载每个类只能有一个析构函数,如果忘记实现析构函数,系统会自动生成一个伪析构函数,由于伪析构函数为空其不能释放动态分配的内存空间。
析构函数的类内实现类似于下面的代码:
class Human { public: ~Human() { //析构函数实现部分 } };
析构函数的类外实现类似于下面的代码:
class Human { public: ~Human(); }; Human::Human() { //析构函数实现部分 };
对象所在的函数已调用完毕时,系统自动执行析构函数;用new开辟了一片内存空间,delete会自动调用析构函数后释放内存;对象A是对象B的成员,B的析构函数被调用时,对象A的析构函数也会被调用。
3.复制构造函数
3.1浅复制及其存在的问题:
当类中包含指针成员,定义的类的对象又作为实参传递给某个函数的形参(即被复制)时,指针成员将被复制。复制后的指针成员和原对象中的指针成员指向同一个内存空间,这被称为浅复制,会威 胁程序的稳定性。
例如下面的程序就存在问题:
#include<iostream> #include<cstring> using namespace std; void strcpy_s(char* pre, const char* next) { if (next != NULL) { while ((*pre++ = *next++) != '