我们知道,类有着隐蔽性,可以把成员变量设为私有变量,这样就可以起到保护成员变量的目的,但是这样我们也就无法为对象的成员赋初值。C++的设计者同样考虑到了这一点,因此就有了构造函数。构造函数是对象在形成的时候由系统调用的一个函数,而且是只能有系统调用。通过这一个函数,我们可以操控函数内部的数据,当然也就可以为变量赋初值了。这个函数的结构书上都写着呢,在这里就不在赘述,本文主要解决一些有歧义的问题。构造函数可以重载,因为它是有参数的。
Date d1(year, month, day);
这样,我们在定义d1这个对象的时候调用了构造函数,并传给了这个函数三个值,这是一种规定,这样写就是在构造一个函数,后面括号里的内容就是在传值,如果没有参数的话,也可以不写括号。
所谓缺省构造函数是指可以不传参的构造函数,有两种形式。第一种是人家构造函数本来就没有参数,第二种形式是所有的参数都有缺省值。(事实上,如果函数里面没有缺省值,而在构造函数的时候有没有给值,编译时是通过的,:C\Users\survf\Desktop\1.cpp|17|error: no matching function for call to ‘Person::Person()’,也就是没有找到这样的函数。)这种函数只能出现一个,因为如果有两个的话,系统不知道去执行。(这句话可能不严谨,不同的编译器不同)。
如果编程者没有给出任何的构造函数,则系统自己构造一个什么也不做的构造函数。这句话一定要注意,因为根据我在VC++6.0和GC++环境下的测试。如果用户给出了拷贝构造函数,这个时候系统就不会自己构造 构造函数,所以说,拷贝构造函数和构造函数一定是同时出现的。
我们知道在C++中有着隐式的类型转换,C++总是会把数据类型转化为需要的数据类型。比如说等号,函数的返回值,函数的参数传递等等。
那么怎么把一个数字转换为一个对象呢,这个时候需要我们人为地给出一些规则。比如说下面我们构造一个复数类,当我们把实数赋给复数类的时候进行强制类型转换,这种转换可以是显示的,也可是隐式的。
#include <iostream>
using namespace std;
class Complex
{
double Real, Image; //实部和虚部
public:
Complex(double x=0, double y=0)
{
Real = x;
Image = y;
cout << "construct " << x << " " << y << endl;
}
};
int main()
{
Complex a=5;
Complex b=Complex(5,3);
return 0;
}
运行结果为
construct 5 0
construct 5 3
析构函数是对象退出作用域的时候自动执行的函数,可以用来清理内存,如果程序中有动态申请的内存才用得到这个函数,虽然这个函数可以用户自己调用,但是我不知道自己调用有什么用。这个函数没有参数,没有返回值,不能重载。
对象退出作用域的时候被撤销,系统调用析构函数。在函数结束的时候,先撤销主函数中的局部对象,再撤销程序中的所有的静态对象。所有静态对象的撤销顺序与建立的顺序相反。
如果用户不自定义析构函数,系统自动建立一个析构函数,什么也不做。
拷贝构造函数是一种构造函数,在通过已知对象给新对象初始化的时候,会由新的对象调用这个函数。注意是初始化而不是赋值,这是因为复制的时候就已经由构造函数初始化过了,所以现在只是赋值,不需要这个函数的。另外要注意的一点是如果有了这个函数的话,系统不会定义缺省的构造函数了,这个前面已经提过。
以下两种情况需要自己写copy函数
如果不是这两种情况的话,直接浅拷贝即可。