构造函数:
1、在类中有一种特殊的成员函数,它的名字和类相同,我们在创建类对象的时候,这个特殊的成员函数会被系统自动调用,所以我们可以简单的理解成:构造函数的目的据说初始化类对象的数据成员。
2、构造函数没有返回值。这也是构造函数的特殊之处。
3、不可以手工调用构造函数,否则编译就会出错。
4、正常情况下构造函数应该被声明为public,因为我们创建一个对象时系统要替我们调用构造函数,这说明构造函数是一个public才能被外界调用,因为类缺省的成员是私有成员,所以我们必须把构造函数声明为public函数,否则无法直接创建该类的对象。
Time myTime = Time(12, 13, 14);
Time myTime2(12, 13, 15);
Time myTime3 = Time{12, 13, 15};
Time myTime4{12, 13, 15};
Time myTime5 = {12, 13, 15};
多个构造函数:
多个构造函数可以为类对象的创建提供多种初始化方法。但是多个构造函数之间要有不同的形参。
对象拷贝时不会调用传统意义上的构造函数,他们调用的不是传统意义上的构造函数,他们调用的实际是拷贝构造函数。
//Time.h
#ifndef __MYTIME__
#define __MYTIME__
class Time {
public:
int Hour;
int Minute;
int Second;
void initTime(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond);
private:
int MillSecond;
void initMillSecond(const int &tmp_millsecond);
public:
Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond);
Time();
};
#endif
//--------------------------------------------------------------------------
//Time.cpp
#include "Time.h"
void Time::initTime(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond) {
Hour = tmp_hour;
Minute = tmp_minute;
Second = tmp_second;
initMillSecond(tmp_millsecond);
}
void Time::initMillSecond(const int &tmp_millsecond) {
MillSecond = tmp_millsecond;
}
Time::Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond) {
Hour = tmp_hour;
Minute = tmp_minute;
Second = tmp_second;
initMillSecond(tmp_millsecond);
}
Time::Time(){
Hour = 12;
Minute = 14;
Second = 16;
initMillSecond(67);
}
//---------------------------------------------------------------------------
//file1.cpp
#include "Time.h"
//对象拷贝
Time myTime;
Time myTime2(myTime);
Time myTime3 = myTime;
Time myTime4 = { myTime };
Time myTime5 { myTime };
函数默认值
规定:
1、默认值只能放在函数声明中,除非该函数没有函数声明。
2、在具有多个参数的函数中指定默认值时,默认参数都必须出现在不默认参数的右边,一旦某个参数开始指定默认值,它右边的所有参数必须指定默认值。
//Time.h
#ifndef __TIME_H_
#define __TIME_H_
class Time{
public:
int Hour;
int Minute;
int Second;
public:
Time(const int &tmp_hour, const int &tmp_minute = 32 , const int &tmp_second = 12);
};
#endif
//--------------------------------------------------------------------------
//Time.cpp
#include "Time.h"
Time::Time(const int &tmp_hour, const int &tmp_minute, const int &tmp_second)
{
Hour = tmp_hour;
Minute = tmp_minute;
Second = tmp_second;
}
隐式转换和explicit
编译器,在私下干了很多我们不了解的事情。
//Time.h
#ifndef __TIME_H_
#define __TIME_H_
class Time{
public:
int Hour;
int Minute;
int Second;
public:
Time(const int &tmp_hour, const int &tmp_minute = 32 , const int &tmp_second = 12);
};
#endif
//--------------------------------------------------------------------------
//Time.cpp
#include "Time.h"
Time::Time(const int &tmp_hour)
{
Hour = tmp_hour;
Minute = 2;
Second = 1;
}
//--------------------------------------------------------------------------
//file.cpp
#include "Time.h"
func(Time tmp_time){
return;
}
Time myTime = 40; //正常情况下是不可以的,但是编译器对 40 做了隐式变换,将40 转换成了 Time(40)
//含糊不清的写法
Time myTime2 = (1, 2, 3, 4); //也编译通过了,执行了 Time(4) 的变换
func(24); //也发生了隐式转换
是否可以强制系统,明确要求构造函数不能做隐式类型转换?可以,如果构造函数声明中带有explicit,则这个构造函数只用与初始化和显示转换。
explicit样例:(注意:要加在函数声明中)
//Time.h
#ifndef __MYTIME__
#define __MYTIME__
class Time {
public:
int Hour;
int Minute;
int Second;
void initTime(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond);
private:
int MillSecond;
void initMillSecond(const int &tmp_millsecond);
public:
explicit Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond);
explicit Time(const int &tmp_hour);
};
#endif
//--------------------------------------------------------------------------
//Time.cpp
#include "Time.h"
void Time::initTime(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond) {
Hour = tmp_hour;
Minute = tmp_minute;
Second = tmp_second;
initMillSecond(tmp_millsecond);
}
void Time::initMillSecond(const int &tmp_millsecond) {
MillSecond = tmp_millsecond;
}
Time::Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond) {
Hour = tmp_hour;
Minute = tmp_minute;
Second = tmp_second;
initMillSecond(tmp_millsecond);
}
Time::Time(const int &tmp_hour){
Hour = tmp_hour;
Minute = 14;
Second = 16;
initMillSecond(67);
}
//---------------------------------------------------------------------------
//file1.cpp
#include "Time.h"
//对象拷贝
Time myTime;
Time myTime2(1, 2, 12, 34); //可以
Time myTime3 = myTime{1, 2, 12, 34}; //可以
Time myTime4 = { 1, 2, 12, 34}; //不可以,说明这个在初始化时发生了隐式类型转换
Time myTime5 { 1, 2, 12, 34 }; //可以
Time myTime = 40; //报错
Time myTime2 = (1, 2, 3, 4); //报错
func(24); //报错
对于单参数的构造函数,一般都声明为explicit,除非有特殊原因。
构造函数初始化列表
专门用来初始化成员变量
//Time.h
#ifndef __MYTIME__
#define __MYTIME__
class Time {
public:
int Hour;
int Minute;
int Second;
private:
int MillSecond;
public:
explicit Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond);
};
#endif
//--------------------------------------------------------------------------
//Time.cpp
#include "Time.h"
void Time::Time(const int &tmp_hour, const int &tmp_minute,
const int &tmp_second, const int &tmp_millsecond)
:Hour(tmp_hour), Minute(tmp_minute), Second(tmp_second), MillSecond(tmp_millsecond)
{
cout << "初始化" << endl;
}
这里初始化列表的初始化顺序,取决于它们声明时的顺序而不是在初始话列表中的顺序。要避免在初始化列表中以用一个成员变量给另一个成员变量赋值。