C++语法详解之封装、构造函数、析构函数

2020-03-07 12:01:29于丽

构造函数(Constructor)

构造函数(也叫构造器),在对象创建的时候自动调用,一般用于完成对象的初始化工作

特点

函数名与类同名,无返回值(void都不能写),可以有参数,可以重载,可以有多个构造函数 一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象

注意

通过malloc分配的对象不会调用构造函数
一个广为流传的、很多教程书籍都推崇的错误结论:
默认情况下,编译器会为每一个类生成空的无参的构造函数
正确理解:在某些特定的情况下,编译器才会为类生成空的无参的构造函数
比如我们自己写2个构造函数

class Person{
public:
 int age;
 
 Person(){
  cout << "Person()" << endl;
 }
 
 Person(int age){
   cout << "Person(int age))" << endl;
 }
};

在不同的空间调用的时候,如下区别

// 全局区
Person p1;  //调用Person()
Person p2(); //这是一个函数,函数名是p2,返回值类型是Person,无参
Person p3(18); //调用 Person(int)

int main(){
 //栈空间
 Person p4;  //调用Person()
 Person p5(); //这是一个函数,函数名是p5,返回值类型是Person,无参
 Person p6(18); //调用 Person(int)
 
 
 //堆空间
 Person *p7 = new Person;  //调用Person()
 Person *p8 = new Person(); //调用Person()
 Person *p9 = new Person(20); //调用 Person(int)
}

析构函数

析构函数(也叫析构器),在对象销毁的时候自动调用,一般用于完成对象的清理工作

特点

函数名以~开头,与类同名,无返回值(void都不能写),无参,不可以重载,有且只有一个析构函数

注意

通过malloc分配的对象free的时候不会调用析构函数 构造函数、析构函数要声明为public,才能被外界正常使用

例如下面的代码

class Cat{
public:
 int age;
 Cat(){
  cout << "Cat()" << endl;
 }
 
 ~Cat(){
  cout << "~Cat()" << endl;
 }
};


class Person{
public:
 int age;
 Cat *cat;
 Person(){
  this->cat = new Cat();
  cout << "Person()" << endl;
 }
 
 ~Person(){
  cout << "~Person()" << endl;
 }
};

int main(){
 {
  Person person;
 }
 return 0;
}

输出

Cat()
Person()
~Person()

当person销毁的时候,其持有的cat并没有销毁。

原因

当person销毁的时候,其指向cat对象的指针销毁了,但是堆空间的cat对象依然存在,就会有内存泄露。所以需要在析构函数里面来释放掉。类似的析构函数在许多其他语言底层也是应用广泛,例如Objective-C的源码中,大量使用析构函数。

代码改成如下所示:

~Person(){
  delete cat;
  cout << "~Person()" << endl;
 }