上一章对所有对象采用一致赋值的方法,即对象调用构造函数,设置初值。但是这样有时候非常不灵活,因为对所有的对象,他们的initial value 都是一致的。有时候我们需要不同对象可能需要不同的初值,如此场景下,有了带参数的构造函数。
1. 带参数的构造函数
构造函数的一般格式为:
构造函数名(类型1 形参1,类型2 形参2,···)
定义对象的一般格式:
类名 对象名(实参1,实参2,···);
#include <iostream>
using namespace std;
class Box
{
public:
Box(int h,int w,int l); // define constructor function
int volume(); //class function
//class function
private: //private data members, unaccessable to public
int height;
int width;
int length;
};
Box::Box(int h,int w, int l)
{
height = h;
width = w;
length = l;
}
int Box::volume()
{
return (height * width * length);
}
int main()
{
Box box1(12,25,30);
cout << "The volume of box1 is " << box1.volume() << endl;
Box box2(15,30,21);
cout << "The volume of box1 is " << box2.volume() << endl;
return 0;
}
Box::Box(int h,int w, int l)
{
height = h;
width = w;
length = l;
}
Box::Box既是通过赋值语句实现了对象的不同初始化工作。
另外还有一种就是用参数初始化表实现对数据成员的初始化。上面可以改成如下形式:
Box::Box(int h, int w, int l):height(h),width(w),length(l){}
这种写法方便、简练,尤其是当需要初始化的数据成员较多时更显优越性。甚至可以直接在类体中(而不是类外)定义构造函数。很多程序员喜欢用这种方法初始化所有的数据成员。
2. 构造函数的重载
在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法,供用户选用。这些构造函数具有相同的名字,而参数的个数或者参数的类型不相同。这称为构造函数的重载。
#include <iostream>
using namespace std;
class Box
{
public:
Box();
Box(int h,int w,int l):height(h),width(w),length(l) {} // define constructor function
int volume(); //class function
//class function
private: //private data members, unaccessable to public
int height;
int width;
int length;
};
Box::Box()
{
height = 10;
width = 10;
length = 10;
}
int Box::volume()
{
return (height * width * length);
}
int main()
{
Box box1;
cout << "The volume of box1 is " << box1.volume() << endl;
Box box2(15,30,20);
cout << "The volume of box1 is " << box2.volume() << endl;
return 0;
}
注意:
(1)在调用函数时,不必给出实参的构造函数,称为默认构造函数。也称缺省构造函数。例如题中的Box()。一个类只能有一个默认构造函数,否则系统无法辨别执行那一个构造函数。如果用户未定义构造函数,系统自动提供一个默认的构造函数,但函数体是空的,不起任何初始化作用。
(2)建立对象是选用的是无参构造函数,那么应该写成
Box box1; //建立正确的默认构造函数
而不是
Box Box box1(); //错误的构造形式,不应该有括号,上面的语句并不是Box类的对象box1,而是一个普通的构造函数box1,此构造函数的返回值为Box类型。
#include <iostream>
using namespace std;
class Box
{
public:
Box(int h = 10,int w = 10,int l = 10); // define constructor function
int volume(); //class function
//class function
private: //private data members, unaccessable to public
int height;
int width;
int length;
};
Box::Box(int h, int w, int l)
{
height = h;
width = w;
length = l;
}
int Box::volume()
{
return (height * width * length);
}
int main()
{
Box box1;
cout << "The volume of box1 is " << box1.volume() << endl;
Box box2(15);
cout << "The volume of box1 is " << box2.volume() << endl;
Box box3(15,30);
cout << "The volume of box1 is " << box3.volume() << endl;
Box box4(15,30,20);
cout << "The volume of box1 is " << box4.volume() << endl;
return 0;
}
这是默认参数的构造函数。好处就是,即使调用构造函数时没有提供实参值,不仅不会出错,而且还确保按照默认的参数值对对象进行初始化。尤其是在希望对每一个对象都有相同的初始化状况时用这种方法更方便,不需要输入数据,对象按事先指定值初始化。
说明:
(1)声明构造函数时指定默认值。因为类的声明是放在头文件中,用户可以到看的,而函数的定义是类的实现细节,用户看不到。
(2)声明构造函数时,形参名可以省略,可以写成
Box (int = 10, int = 10, int = 10);
(3) 一个类只有一个默认的构造函数。如果同时定义了下面两个构造函数,是错误的。
Box(); //声明了一个无参的构造函数
Box(int = 10, int = 10, int = 10); //声明了一个全部的参数,都指定了默认值的构造函数。
因为在建立对象时,如果写成
Box box1;
编译系统无法识别哪个调用了构造函数,出现了歧异,编译时报错。
(4)在一个类中,如果定义了全是是默认参数的构造函数后,不能再定义重载构造函数。因为编译时会出现歧异。因此,一般不能出现同时使用构造函数的重载和有默认参数的构造函数。