构造函数和析构函数 <一>

构造函数是类的一种特殊成员函数。当创建一个类类型的对象时,系统会默认调用构造函数。在C++中,在类中定义的函数,都是可以抽象成一种方法。于是构造函数也是为类的对象服务的一种方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们,即构造函数的重载

构造函数的要点:

         1.构造函数的命名必须和类名完全相同。在java中普通函数可以和构造函数同名,但是必须带有返回值;

         2.构造函数的功能主要用于在类的对象创建时定义初始化的状态。它没有返回值,也不能用void来修饰。这就保证了它不仅什么也不用自动返回,而且根本不能有任何选择。而其他方法都有返回值,即使是void返回值。尽管方法体本身不会自动返回什么,但仍然可以让它返回一些东西,而这些东西可能是不安全的;

         3.构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的;

         4.当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数.此默认构造函数是不带参数的。而一般的方法不存在这一特点;

         5.当一个类只定义了私有的构造函数,将无法通过new关键字来创建其对象,当一个类没有定义任何构造函数,C#编译器会为其自动生成一个默认的无参的构造函数。

         6.构造函数有回滚的效果,构造函数抛出异常时,构造的是一个不完整对象,会回滚,将此不完整对象的成员释放(c++)

构造函数和析构函数的内容很丰富,暗藏很多内部细节,下面就对这些情况讨论:

//****对象创建时即自动调用构造函数****
#include<iostream>
using namespace std;
class Test
{
public:
    Test()   //不带参数的构造函数是默认的构造函数,构造函数通常声明为公有的。
    {
        num=1;
        cout<<"Default function!"<<endl;//将这里的赋值和打印语句去掉,
        cout<<"num = "<<num<<endl;      //就等同于系统默认的构造函数,
                                       //即函数体为空,什么也不做
    }
private:
    int num;
};
int main()
{
    Test a;
    return 0;
}
程序运行结果:


/***如果不声定义构造函数,系统则默认生成一个不带参数和返回值,
    且为空的默认构造函数。
    但一旦定义了带参数的构造函数,那么系统则不生成默认的构造函数
    演示带参数的构造函数不是系统默认的构造函数***************/
#include<iostream>
using namespace std;
class Test
{
public:
    Test(int nu);//带参数的构造函数
    {
        num=nu;
        cout<<"num = "<<num<<endl;
    }
private:
    int num;
};
int main()
{
    Test a;//尝试调用系统默认的构造函数,不成功
    return 0;
}
此时会报错:找不到默认的构造函数


/****带参数的构造函数,系统不再提供默认的构造函数****/
#include<iostream>
using namespace std;
class Test
{
public:
    Test()
    {
        cout<<"Call default function"<<endl;
    }
    Test(int nu)   //带参数的构造函数,系统不再提供默认的构造函数
       {
        num=nu;
        cout<<"Initialing function!"<<endl;
        cout<<"num = "<<num<<endl;
       }
private:
    int num;
};
int main()
{
    Test a(10);//传递参数,调用带参数的构造函数
    return 0;
}
程序运行结果:


可以看到,默认的构造函数并没有执行。

//******new运算符创建对象时调用构造函数*****
#include<iostream>
using namespace std;
class Test
{
public:
    Test(int nu)//带参数的构造函数
    {
        num=nu;
        cout<<"Call Test(**) success!"<<endl;
        cout<<"num = "<<num<<endl;
    }
private:
    int num;
};
int main()
{
    Test* t3 = new Test(12);//调用new分配空间的同时,调用构造函数
    delete  t3;
	return 0;
}
程序运行结果:


析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。析构函数不带参数,于是不能被重载。

         下面讨论析构函数与构造函数的内容:

/******delete运算符撤销对象时调用析构函数******/
#include<iostream>
using namespace std;
class Test
{
public:
    Test(int nu)//带参数的构造函数
    {
        num=nu;
        cout<<"Call Test(**) success!"<<endl;
        cout<<"num = "<<num<<endl;
    }
    ~Test()
    {
        cout<<"num has been distroyed !"<<endl;
    }
private:
    int num;
};
int main()
{
    Test* t3=new Test(12);//调用new分配空间的同时,调用构造函数
    delete t3;//使用delete释放t3时,调用析构函数
    return 0;<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

/****** delete运算符撤销对象时调用析构函数******/
#include<iostream>
using namespace std;
class Test
{
public:
    Test();
    Test(int nu);
    ~Test();
private:
    int num;
};
Test::Test()
    {
    num=0;
    cout<<"num = "<<num<<endl;
    }
Test::Test(int nu)
    {
    num=nu;
    cout<<"num = "<<num<<endl;
    }
Test::~Test()
    {
        cout<<num<<" has been distroyed !"<<endl;
    }
int main()
{
    Test t1;
    Test t2(10);
    Test* t3=new Test(12);//调用new分配空间的同时,调用构造函数
    delete t3;//由程序员释放堆上的内存
    return 0;
}//花括号运行后,t1,t2被撤销,此时调用析构函数,
 //且顺序和调用构造函数相反

/*****全局对象的构造函数先于main函数,析构函数后于main函数**/
#include<iostream>
using namespace std;
class Test
{
public:
    Test();
    Test(int nu);
    ~Test();
private:
    int num;
};
Test::Test()
    {
    num=0;
    cout<<"num = "<<num<<endl;
    }
Test::Test(int nu)
    {
    num=nu;
    cout<<"num = "<<num<<endl;
    }
Test::~Test()
    {
        cout<<num<<" has been distroyed !"<<endl;
    }
Test t1(12);//这里先于main函数,调用了构造函数
int main()
{
    cout<<"Entering main...."<<endl;
    return 0;
}//全局对象的析构后于Main函数

</pre><pre name="code" class="cpp">/****演示对象数组与构造函数和析构函数的关系****/
#include<iostream>		using namespace std;
class Test
{
public:
    Test();
    Test(int nu);
    ~Test();
private:
    int num;
};
Test::Test()
    {
    num=0;
    cout<<"num = "<<num<<endl;
    }
Test::Test(int nu)
    {
    num=nu;
    cout<<"Initialing num"<<endl;
    cout<<"num = "<<num<<endl;
    }
Test::~Test()
    {
        cout<<num<<" has been distroyed !"<<endl;
    }

int main()
{
    Test t[2]={10,20};
    Test* t2=new Test(2);
    delete t2;//最先调用析构函数
    Test* t3=new Test[2];//对象创建数组
    delete[] t3;//撤销对象数组,调用两次析构函数
    return 0;
}//撤销t[1],t[2],调用两次析构函数


/*******演示显式调用析构函数,尽量不要这样做***/
#include<iostream>
using namespace std;
class Test
{
public:
    Test();
    Test(int nu);
    ~Test();
private:
    int num;
};
Test::Test()
    {
    num=0;
    cout<<"num = "<<num<<endl;
    }
Test::Test(int nu)
    {
    num=nu;
    cout<<"Initialing num"<<endl;
    cout<<"num = "<<num<<endl;
    }
Test::~Test()
    {
        cout<<num<<" has been distroyed !"<<endl;
    }

int main()
{

    Test t2(2);
    t2.~Test();//显式调用析构函数
    return 0;
}//对象生命周期结束,销毁对象,再次调用析构函数

有关这部分的内容真的很丰富,写了将近3个多小时,好累,就先说到这里。未完待续。。。。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值