关于构造函数的认识:在建立一个对象时,常常需要做某些初始化工作,例如如何给数据成员赋初值。如果一个数据成员未被赋值,则他的值是不可预知的,因为系统在为它分配内存时,保留了这些存储单元的原状,这就成为了数据成员的初始值。这种情况显然是与人们的要求不相符的,对象是一个实体,它反映了客观事物的属性,是应该有确定值的。
但是数据成员是不能在声明类时初始化
如例1、
class Data{
int year=2;
int month=12;
int day=31;
};
为什么不能在不能在声明类时对数据成员初始化?
因为类并不是一个实体,而是一种抽象的数据类型,并不占存储空间,显然无法容纳数据。
如果一个类中所有的成员都是公用的,则可以在定义对象时对数据成员进行初始化。
例2、
class Data{
public:
int year=2;
int month=12;
int day=31;
};
构造函数的作用:构造函数是一种特殊的成员函数,与其他成员函数不同。不需要用户来调用它,而是在创建类对象时,由编译器自动调用。构造函数的名字与类名相同,而不能由用户任意命名,以便编译系统能识别它并把它作为构造函数处理 。它不具有任何类型,也没有返回值。构造函数的功能是由用户自己定义的,用户根据初始化的要求设计函数体和函数参数。
例3、
class Time
{
public:
Time()
{
hour = 0;
minute = 0;
second = 0;
}
void setTime();
void showTime();
private:
int hour;
int minute;
int second;
};
int main()
{
Time t;
t.setTime();
t.showTime();
system("pause");
return 0;
}
void Time::setTime()
{
cin >> hour;
cin >> minute;
cin >> second;
}
void Time::showTime()
{
cout << hour << ":" << minute << ":" << second << endl;
}
我们可以看出在这个程序里定义了一个构造函数,在建立对象时自动执行构造函数,它的作用是为该对象中的各数据成员赋初值0。
程序运行时首先建立对象t,并对t中的数据成员赋初值0,然后再执行setTime()函数,从键盘输入新值给对象t中的数据成员,再执行showTime()函数输出数据成员的值。
带参数的构造函数:
在上面的例子我们可以看出这个构造函数是不带参数的,在函数体中对个数据成员赋初值。这种方式使该类的每一个对象都得到同一组初值。但是用户有时希望对不同的对象赋予不同的初值,这时就需要我们采用带参数的构造函数
构造函数名(类型1形参1,类型2形参2....)
前面我们可以知道用户是无法调用构造函数的,因此无法采用常规的调用函数的方法给出实参如fun(a,b)。实参是定义对象时给出的,定义对象的一般格式为:
类名 +对象名(实参1,实参2)
例4、有连个长方柱,其长宽高分别为:(1)12,25,30(2)15,30,21分别求他们的体积。
class Box{
public:
Box(int a, int b, int c)//构造函数名(类型1形参1,类型2形参2....)
{
length= a;
width = b;
hight = c;
}
int value()
{
return (length*width*hight);
}
private:
int length;
int width;
int hight;
};
int main()
{
Box t1(12,25,30), t2(15,30,21);//类名 + 对象名(实参1,实参2)
cout << "the result1 is :" << t1.value() << endl;
cout << "the result2 is :" << t2.value() << endl;
system("pause");
return 0;
}
用参数初始化列表对数据成员初始化
在构造函数的函数体内通过赋值语句对数据成员实现初始化,C++还提够另一种初始化数据成员的方法------参数初始化列表来实现对数据成员的初始化。这种方法不在函数体内对数据成员初始化,而是在函数首部实现
例如将上述例子中定义的构造函数可以修改成如下形式:
class Box{
public:
Box(int a, int b, int c);//构造函数名(类型1形参1,类型2形参2....)
int value()
{
return (length*width*hight);
}
private:
int length;
int width;
int hight;
};
Box::Box(int a, int b, int c)//构造函数名(类型1形参1,类型2形参2....)
:length(a)
, width(b)
, hight(c)
{
}
/*length = a;
width = b;
hight = c;*/
int main()
{
Box t1(12,25,30), t2(15,30,21);//类名 + 对象名(实参1,实参2)
cout << "the result1 is :" << t1.value() << endl;
cout << "the result2 is :" << t2.value() << endl;
system("pause");
return 0;
}
构造函数的重载‘例5、
class Box{
public:
Box();
Box(int a, int b, int c) //构造函数名(类型1形参1,类型2形参2....)
:length(a)
, width(b)
, hight(c)
{
}//在类体中直接定义构造函数
int value()
{
return (length*width*hight);
}
private:
int length;
int width;
int hight;
};
//Box::Box(int a, int b, int c)//构造函数名(类型1形参1,类型2形参2....)
// :length(a)
// , width(b)
// , hight(c)
// {
//
//}
/*length = a;
width = b;
hight = c;*/
Box::Box()
{
hight = 10;
width = 10;
length = 10;
}
int main()
{
Box t3;
cout << "the result3 is :" << t3.value() << endl;
Box t1(12,25,30), t2(15,30,21);//类名 + 对象名(实参1,实参2)
cout << "the result1 is :" << t1.value() << endl;
cout << "the result2 is :" << t2.value() << endl;
system("pause");
return 0;
}
第一个构造函数是没有参数的,是在类体外直接对数据成员进行赋值的。第二个构造函数是直接在类体内定义的。这两个构造函数进行了重载
说明:在调用构造函数时不必给出实参的构造函数称为默认的构造函数或者缺省构造函数。
一个类只能有一个默认的构造函数,否则系统就无法辨别应该执行哪个构造函数。
构造函数是不能被用户显式调用的
尽管在一个类中可以有多个构造函数,但是对每一个对象来说,建立对象时只执行一个构造函数并非每个构造函数都被执行。
使用默认参数的构造函数:
构造函数中参数的值既可以进行实参传递,也可以制定某些默认值,即如果用户不指定实参值 ,编译系统就使形参取默认值。
例6、将构造函数改用默认值的参数、长、宽、高的默认值均为10 。
#include<iostream>
#include<stdlib.h>
using namespace std;
class Box
{
public:
Box(int h = 10, int w = 10, int len = 10);//在声明构造函数时指定默认参数
int volume();
private:
int height;
int width;
int length;
};
Box::Box(int h, int w, int len)//在类体外定义构造函数
:height(h)
,width(w)
, length(len)
{
}
int Box::volume()
{
return(height*width*length);
}
int main()
{
Box box1;
cout << "the value of box1 is " << box1.volume() << endl;//没有给定实参系统就调用默认的构造函数值都是10
Box box2(15);
cout << "the value of box1 is" << box2.volume() << endl;//给定了一个实参,它就传给形参,未得到实参的就取默认值
Box box3(15,20);
cout << "the value of box1 is" << box3.volume() << endl;//同理
Box box4(15, 20, 30);
cout << "the value of box1 is" << box4.volume() << endl;
system("pause");
return 0;
}
说明:
应该在声明构造函数时指定默认值,而不应该在定义构造函数时指定默认值。
在声明构造函数的时候,形参名可以省略。
如果一个构造函数的的全部形参都指定了默认值,则在定义一个对象时可以不给出实参也可以给出几个实参
一个类只能有一个默认的构造函数,一个构造函数的的全部形参都指定了默认值也是默认的构造函数,
如上述例子。
.