构造函数是类的一种特殊成员函数。当创建一个类类型的对象时,系统会默认调用构造函数。在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个多小时,好累,就先说到这里。未完待续。。。。