C++ 构造函数和析构函数(Constructors & Destructors)详解

 更新时间:2024年05月05日 09:20:24   作者:阮春义  
由于global object的诞生比程序进入更早点,所以global object的constructor执行的时间更早于程序的进入点,所谓的default constructor就是没有指定任何的参数的constructor,这篇文章主要介绍了C++ 构造函数和析构函数的相关知识,需要的朋友可以参考下

一、定义:

  当object产生,有一个特殊的称为constructor的函数会自动执行。当object死亡,有一个特殊的称为destructor的函数会自动执行。Constructor 可以不只一个,但 destructor 只能有一个。

  Constructor(构造函数)就是与class同名的那些member functions,例如CPoint::CPoint()或CDemo::CDemo()。Constructors不能够指定返回值类型,也就是它不必(但可以)return。constructions可以有一个或多个,各有不同类型的参数。

  Destructor(析构函数)就是与class同名,且前面有加“~”符号的那个member function,例如例如 CPoint::~CPoint() 或 CDemo::~CDemo()。Destructor 不能指定返回值类型,也就是它不必(但可以)return。每个class只有一个destructor,并且不能有任何参数。

  由于global object的诞生比程序进入更早点,所以global object的constructor执行的时间更早于程序的进入点。

二、Default Constructors

  所谓的default constructor就是没有指定任何的参数的constructor。如果我们的class CA声明如下:

#include <iostream>
using namespace std;
class CA
{
 public:
    int getdata(){return _data;};
    CA(){_data =5;};
    CA(int val){_data =val;};
 protected:
    int _data;
};

  CA有两个constructors,分别是CA(int) 和 CA()。后都没有参数,正是所谓的default constructor。当我产生一个 CA object 而沒有指定任何参数:

 CA aCA;
 CA* pCA = new CA;

  编译器就为我们呼叫default constructor。

  普遍存在于C++程序员之间的一个误解是:如果我们没有为某个class设计constructor,编译器会自动为该class制造出一个default constructor来。这个说法也对也不对,这里我先提示一个结论,销稍后有更多细节探讨。什么是编译器所需要的动作?就是隐藏在C++程序代码下面,让C++诸多特征得到实现的动作,包含以下三种情况:

  1. class CA 內 含 class CZ objects,如图1:当产生一个CA object 时,隐藏在底层的必要动作是先初始化CZ object(因为CA object中有一个CZ object)

  2.class CA继承于class CZ,如图2:当产生一个CA object 时,隐藏在底层的必要动作是先调用CZ的default constructor (因为CA object中有一个CZ subobject)

  3.CA是一个 polymorphic class,也就是说它有virtual functions,或继承于有virtual functions的class。当产生一个CA object,隐藏在底层的必要动作是:将虚拟机制所需要的vptr和vtb1初始化。

  由于这三种情况皆有所谓的“底层的必要动作”,所以编译器必须自动为class CA生成一个default constructor((如果沒有任何 user-defined constructor 的话),或暗中对已有的user-defined constructor 动作脚(添加一些代码)。生成出来的东西称为“implicit nontrivial default constructor”。

  如果沒有上述需求,编译器就不会为class产生一个default constructor,例如: 

class CB
{ public:
int getdata() { return _data; };
protected:
int _data;
};

 

virtual functions的base classes),也没有内含embedded objects,也没有继承于其它class,所以编译器不会为它生成一个default constructor出来,于是当我们这么做:

 CB aCB; // 应该调用default constructor
 cout << "aCB.getdata()=" << aCB.getdata() << endl;

  但得到的结果如下:

aCB.getdata()=4211382 // 莫名其妙的初值

  这个恐怕不是我所期望的,我们期望的_data有个初始值,但这个不是编译器的需求,所以我们只能自求多福,自已设计一个default constructor:

 class CB
 { public:
     int getdata() { return _data; };
         CB() { _data = 5; }; // default constructor
 protected:
     int _data;
 };

  现在输出的结果就是我们所期望的了:

CB aCB; // 应该调用  default constructor
cout << "aCB.getdata()=" << aCB.getdata() << endl;
// 输出结果:aCB.getdata()=5

  注意,如果class已经有了任何constructor,但不是default constructor,编译器绝不会为它生成一个default constructor。如果class CZ正是如此一个class,那么当你想产生一个CZ object,并且没有指定参数时:

CZ *aCZ; // error

  编译器会输出异常提示:

error C2512: 'CZ' : no appropriate default constructor available

三、Copy Constructors

  所谓的Copy Constructors是指有一个参数的类型是其 class type的 constructor,例如:

class CA
{
public:
    int getdata() {return _data; };     //default constructor
    CA(){_data =5;};
    CA(int val){_data=val; };           //constructor
    CA(const CA& ca){                  //copy constructor
        cout<<"copy constructor"<<endl;
        _data=10;
    };
protected:
    int _data;
};

   以下两种情况,会唤起copy constructor:

  情况1:将一个object当做参数传给某一个函数;

  情况2:将一个object当做函数的返回值;

  例如(沿用上面的class CA):

#include <iostream>
using namespace std;
class CA
{
public:
    int getdata() {return _data; };     //default constructor
    CA(){_data =5;};
    CA(int val){_data=val; };           //constructor
    CA(const CA& ca){                  //copy constructor
        cout<<"copy constructor"<<endl;
        _data=10;
    };
protected:
    int _data;
};
void foo2(CA aCA)//情况1(函数参数是个object)
{
    cout<<"in foo2(),aCA.getdata()="<<aCA.getdata()<<endl;
}
CA foo3()//情况2(函数的返回值是个object)
{
    CA aCA(3);
    cout<<"in foo3(),aCA.getdata()="<<aCA.getdata()<<endl;
    return aCA;
}
int main()
{
    CA aCA1,aCA2(7);
    cout << "aCA1.getdata()="<<aCA1.getdata()<< endl;
    cout << "aCA2.getdata()="<<aCA2.getdata()<< endl;
    aCA2 =aCA1;//object assignment
    cout << "aCA2.getdata()="<<aCA2.getdata()<< endl;
    foo2(aCA1);//情况1(调用之前aCA1._data 为5)
    aCA2=foo3();
    cout << "aCA2.getdata()="<<aCA2.getdata()<< endl;
    return 0;
}

  让我们看看执行结果:

aCA1.getdata()=5
aCA2.getdata()=7
aCA2.getdata()=5 // 经过 object assignment 之后
copy constructor
in foo2(), aCA.getdata()=10 // 经过情況 1 之后
in foo3(), aCA.getdata()=3
copy constructor
aCA2.getdata()=10 // 经过情況 2 之后

  这里有几点需要注意的:

  1. 38行的将一个object指派(assign)给另一个object,这也是一种复制,但它唤起的所谓的copy assignment operator。本例并没有特别设计copy assignment operator;

  2.调用foo2()之前,_data为5,进入foo2()之后再输出,已变成10,可见copy constructor的确在foo2()的参数复制时发生;

  3.foo3()内有一个local object,其_data为3,把穹当做返回值输出,却变成了10,可见copy constructor的确在foo3()的返回值复制时发生;

到此这篇关于C++ 构造函数和析构函数(Constructors &amp; Destructors)详解的文章就介绍到这了,更多相关C++ 构造函数和析构函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解析c语言switch中break语句的具体作用

    解析c语言switch中break语句的具体作用

    以下是对c语言switch中break语句的作用进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • OpenCV实现视频绿幕背景替换功能的示例代码

    OpenCV实现视频绿幕背景替换功能的示例代码

    这篇文章主要介绍了如何利用OpenCV实现视频绿幕背景替换功能,文中的示例代码讲解详细,对我们学习OpenCV有一定的帮助,感兴趣的可以学习一下
    2023-02-02
  • C++常用字符串函数大全(2)

    C++常用字符串函数大全(2)

    这篇文章主要给大家分享的是C++常用字符串函数的大全,cstring.h库即C语言中的string.h库,它是C语言中为字符串提供的标准库。C++对此进行了兼容,所以我们在C++当中一样可以使用,下面文章的详细内容,需要的朋友可以参考一下
    2021-11-11
  • 减小VC6编译生成的exe文件的大小的方法

    减小VC6编译生成的exe文件的大小的方法

    这篇文章主要介绍了减小VC6编译生成的exe文件的大小的方法,需要的朋友可以参考下
    2015-01-01
  • C&C++设计风格选择 命名规范

    C&C++设计风格选择 命名规范

    本文难免带有主观选择倾向,但是会尽量保持客观的态度归纳几种主流的命名风格,仅供参考
    2018-04-04
  • C语言实现员工工资管理系统

    C语言实现员工工资管理系统

    这篇文章主要为大家详细介绍了C语言实现员工工资管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • C++ for循环与nullptr的小知识点分享

    C++ for循环与nullptr的小知识点分享

    这篇文章主要是来和大家介绍一些C++中的小知识点,本文分享的是for循环与nullptr,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-05-05
  • C语言 动态内存分配的详解及实例

    C语言 动态内存分配的详解及实例

    这篇文章主要介绍了C语言 动态内存分配的详解及实例的相关资料,需要的朋友可以参考下
    2016-09-09
  • 使用emacs编写C语言教程

    使用emacs编写C语言教程

    这篇文章主要介绍了使用emacs编写C语言教程,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言中%c与%s的区别与划分详解

    C语言中%c与%s的区别与划分详解

    这篇文章主要介绍了C语言中%c与%s的区别与划分详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12

最新评论