一、构造函数
是为了让我们自己去规定 , 我们定义对象的初始化。
这里给出一段程序,作用是按格式输出 输入的时间。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Clock{
public:
void setTime(int newS = 0, int newM = 0, int newH = 0){
//这一步如果想要输出默认值,应该把主函数里的setTime函数中的参数删除。
second = newS;
minute = newM;
hour = newH;
}
void showTime();
private:
int second, minute, hour;
};
void Clock::showTime(){
cout << hour << ":" << minute << ":" << second <<endl;
}
int main(){
Clock MyClock;
int second, minute, hour;
cin >> second >> minute >> hour;
MyClock.setTime(second, minute, hour);
MyClock.showTime();
return 0;
}
构造函数的性质:
● 不能定义返回值类型,也不能写return语句
●可以有形参,也可以没有形参,可以带有默认参数
●函数名必须和类名完全相同
●可以重载
当我们没有写构造函数时,系统会为我们自动生成一个默认构造函数,这个默认构造函数的参数列表和内容都是空的,所以他什么都不会做!
现在 我们需要创建一个默认构造函数,让对象早初始化的时候把所有的时间全部设置为0。
//在类内定义构造函数时,不能有返回值类型,且构造函数的名字要和类一样,可以有形参也可以没有形参,这里的第一种定义是没有形参的类型:
class Clock{
public:
Clock(){
second = 0;
minute = 0;
hour = 0;
}
//如果不写构造函数,那么系统自动生成的构造函数 就是
Clock(){}
//函数里没有任何内容,所以也不会有操作
第二种定义类型是有参数的形式:
Class Clock{
public:
Clock(int newS, int newM, int newH){
second = newS;
minute = newM;
hour = newH;
}
}
//或者在类外实现构造函数
Class Clock{
public:
Clock(int newS, int newM, int newH);
}
Clock::Clock(int newS, int newM, int newH){
second = newS;
minute = newM;
hour = newH;
}
这里在类外实现构造函数时,函数名前面仍然不要写函数的返回值类型 ,
实现类外构造函数 : 在类内对函数定义,然后在类外 用
类名 :: 函数名 ( 参数 ) { 函数体 } 的形式在类外实现构造函数。
而在类外实现普通函数时,也是在类内先对函数进行定义,然后在类外 用
返回值类型 类名 :: 函数名 ( 参数 ) { 函数体 } 实现,这里需要在类
名前面加上返回值类型
调用带参数的构造函数时,是在对象创建时被调用的:
Clock MyClock2(1,2,3);
二、复制构造函数
用一个已有的对象,来执行一个新的对象的构造
●复制构造函数具有一般构造函数的所有特性,它的形参是本类的一个对象的引用,作用是用一个已经存在的对象(函数的参数)来初始化一个新的对象。
●复制构造函数的的使用方式 就是引用传参。
引用就是 给一个已经存在的变量起一个别名,所以用它的变量名或者别名都可以操作该变量, 复制构造函数就是给已经存在的构造函数起一个别名。
因为:值传递就是当函数发生调用的时候,给形参分配内存空间,然后用实参的值来初始化形参,但是如果参数是一个对象,值传递“初始化形参”这个过程就会造成很多额外的时间开销,浪费系统资源,如果使用引用就不会有这样的问题。
复制构造函数能实现同类对象之间数据成员的传递。 当我们没有定义类的构造韩函数时,系统就会在必要的时候自动生成一个隐含的复制构造函数,他的作用是把初始对象的每一个数据成员的值都复制到新建的对象中,这就完成了同类对象的复制。
复制构造函数的具体声明方式 :
class 类名{
public:
类名(类名& 对象名){
//实现
}
};
实例:
先有一个point类,表示屏幕上的一个点——它包括两个 int 类的私有成员 x , y, 表示这个点的坐标。
class Point {
public:
Point(Point &p);
private:
int x,y;
};
//以下代码可实现复制构造函数
Point::Point(Point &p){
x = p.x;
y = p.y;
}
//这里复制构造函数访问了Point类的实例对象p的两个私有成员变量 x,y 。我们需要注意的是 ———— private 与 public 的区别是对类来说的,而不是对对象来说。 拷贝构造函数是Point类的成员函数————所以它可以访问类的私有成员变量,这跟具体的对象无关。
复制构造函数被调用主要的三种情况:
●当用类的一个对象去初始化该类的另一个对象的时候:
Point a(1,2);
Point b(a);//用对象a初始化对象b,复制构造函数被调用
Point c = b;//用对象b给对象c赋值,复制构造函数被调用
●当函数的形参是类的对象,调用函数是进行形式结合的时候:
void f(Point p){
//函数体
}
int main(){
Point a(1,2);
f(a);
return 0;
}
●当函数返回值是类的对象,函数执行完成返回调用者的时候:
Point g(){
Point a(1,2);
return a;
}
/*定义在函数中的变量都是局部变量,当函数返回值的时候这些局部变量
都被销毁了。同样,在函数中创建的对象也相同。 return a 这一步返
回的并不是 a 这个对象本身,而是通过复制构造函数,在主调函数中用a
重新构造的对象。在函数调用返回的时候,原来的临时对象 a 的使命已
经完成,随着整个函数中的其他临时变量一起被销毁了。*/
对于复制构造函数,我们还可以自己实现一些有选择、有变化的复制:
Point (point &p){
x = p.x+10;
p=p.y;
}
这个函数就会把每一个由复制构造得到的Point对象,横坐标+10.