C++知识文档五_构造函数和析构函数

来源:互联网 发布:tim linux 编辑:程序博客网 时间:2024/06/06 02:19

构造函数和析构函数

  构造函数  构造函数是类的一种特殊成员函数,一般情况下,构造函数是专门用来初始化对象成员变量的,所以最好不要在构造函数中进行与对象的初始化无关的操作。构造函数在类实例化对象时自动执行,构造函数的名字必须与类名同名,它不具有任何类型,不返回任何值,即使是void也不允许。

  *当没有定义构造函数时,编译器会提供默认构造函数,在某些情况下,编译器未提供构造函数,经过O2编译选项优化之后简单结构的类会变成连续定义的变量。

    可以通过反汇编查看到对象定义时不会产生反汇编代码。

例4.演示各种特殊构造函数的用法(请留意代码中的详细注释)

classCTest

{

protected:

   int m_i1;

   int m_i2;

public:

   void Print()

   {

      printf("m_i1:%dm_i2:%d\n",m_i1,m_i2);

   }

   /*

   缺省构造函数,如果定义类时未指定任何构造函数,

   系统将自动生成不带参数的缺省构造函数

   */

   CTest()

   {

      m_i1=0;

      m_i2=0;

   } 

   /*

   带一个参数的可用于类型转换的构造函数

   */

   CTest(int i1)

   {

      m_i1=i1;

      m_i2=0;

   }

   /*

   带参数的构造函数

   */

   CTest(int i1,int i2)

   {

      m_i1=i1;

      m_i2=i2;

   }

   /*

   拷贝构造函数,如果此函数不定义,系统将生成缺省拷贝构造函数功能,

   缺省拷贝构造函数的行为是:用传入的对象参数的成员初始化正要建立的对象的相应成员

   */

   CTest(const CTest &oTest)

   {

      m_i1=oTest.m_i1;

      m_i2=oTest.m_i2+2;    //区别于缺省拷贝构造函数的行为

   }

   /*

   析构函数,一个类中只能有一个析构函数,如果用户没有定义析构函数,

   系统会自动未类生成一个缺省的析构函数

   */

   ~CTest()

   { 

   }

};

intmain(int argc, char* argv[])

{

   CTest test1;     //调用缺省构造函数

   CTest test2();      //这是函数的声明,不是实例化类

   CTest test3(1);     //调用带一个参数的构造函数

   CTest test4(1,2);   //调用带多个参数的构造函数

   CTest test5=5;      //等价于CTest test5(5);

   //等价于CTest test6(6);

   CTest test6=CTest(6);

   //生成临时对象CTest(5),并把该对象的成员赋值给对象test1

   test1=5;

   //生成临时对象CTest(6,66),并把该对象的成员赋值给对象test1

   test1=CTest(7,77);   

   CTest test8(test1); //调用拷贝构造函数

   CTest test9=test1;  //等价于CTest test9(test1)

   //对象间的赋值,将test9的成员值逐个赋值给test1的成员

   test1=test9;    

   return 0;

}

注意:以上代码实例中,我们可以看出:一个类只有一个构造函数,但是可以有多个构造函数。不同的构造函数具有相同的函数名,但是具有不同的参数个数以及类型,系统根据所传入的参数类型和个数决定需要调用那一个函数。这成为函数的重载。

初始化成员列表   通常在类的构造函数的函数体中初始化类的成员数据,除此外还可以通过初始化成员列表的方式初始化数据成员。

初始化成员列表的形式为:构造函数名(构造函数参数列表):成员1(参数列表1),成员2(参数列表2),,,成员n(参数表n)。

例5、使用初始化成员列表的方式实现构造函数对类的数据成员初始化

classCTest1

{

private:

   int m_iRef;

public:

   CTest1(int iRef)

   {

      m_iRef=iRef;

   }

};

classCTest2

{

private:

   int m_i1;

   int m_i2;

   const int m_iConst;

   //const int m_iConst=0;//请思考:为什么不能在这里直接对该类的数据成员进行初始化?

   CTest1 m_obj;

public:

   CTest2();

};

CTest2::CTest2():m_i1(1),m_iConst(4),m_obj(0)

{

   m_i2=2;

}

注意:以下两种情况必须要使用初始化成员列表的方式来对类的数据成员进行初始化:

类的成员是常量成员初始化    对常量成员赋初始值只能在初始化成员列表中。

类的成员是对象成员初始化    对象成员必须用带参数的构造函数初始化,则该对象成员的初始化必须在初始化成员列表中。


析构函数 

对象的生命期结束时,会自动调用析构函数。析构函数名是在类名前加"~",析构函数同样不能返回任何值,也没有函数参数,并且不能被重载,所以一个类可以有多个构造函数,却只能有一个析构函数。

一般说来,每当创建一个对象时就调用对象的构造函数;每当撤消一个对象就调用该对象的析构函数。具体有以下4种情况:

  对于全局定义的对象,每当程序开始运行,在主函数main(或WinMain)接受程序控制权之前,就调用全局对象的构造函数。整个程序结束时调用析构函数。

  对于局部定义的对象,每当程序流程到达该对象的定义处就调用构造函数,在程序离开局部变量的作用域时调用对象的析构函数。

  对于关键字static定义的局部变量,当程序流程第一次到达该对象定义处调用构造函数,在整个程序结束时调用析构函数。

  对于用new运算符创建的对象,每当创建该对象时调用构造函数,当用delete删除该对象时,调用析构函数。

  参数对象:退出函数前,调用参数对象的析构函数

  返回对象: 若无对象引用,退出函数后,调用返回对象的析构函数,否则与对象引用的作用域一致。


0 0
原创粉丝点击