初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
示例:
class A
{
public:
A(int year, int month, int day)
: _year(year)
,_month(month)
,_day(day)
{
}
private:
int _year;//声明
int _month;
int _day;
};
注意:
class B
{
public:
B(int b)
: _ret(b)
{
}
private:
int _ret;
};
class A
{
public:
A(int a, int n)
: _a(a)
, _n(n)
, _b(5)
{
}
private:
int& _a;//引用
const int _n;//const
B _b;//自定义类型
};
构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用。
匿名对象:
class A
{
public:
explicit A(int n)
: _n(n)
{
}
A(const A& a)
: _n(a._n)
{
}
private:
int _n;
};
int main()
{
A a1(1);//他的生命周期在main函数域
A(5);//匿名对象,他的生命周期在这一行
A a2 = 5;
//隐式类型转换,结果调用构造函数 -> 先构造一个A(5)匿名临时对象,
//再用临时对象拷贝构造a2
return 0;
}
用explicit修饰构造函数,将会禁止单参构造函数的隐式转换。
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。
面试题:实现一个类,计算中程序中创建出了多少个类对象?
class A
{
public:
A()
{
++count_A;
}
A(const A& a)
{
++count_A;
}
//静态成员函数没有this指针
static int GetCountA()
{
return count_A;
}
private:
//静态成员变量属于类的所有对象,属于整个类
static int count_A;
};
//定义初始化
int A::count_A = 0;
int main()
{
A a1;
A a2;
A a3;
A a4(a1);
A a5(a2);
//如果没有访问限定符的限制,指定类域就可以访问静态成员
cout << A::count_A << endl;
cout << a1.GetCountA() << endl;//对象.访问
cout << A::GetCountA() << endl;//类名::访问
return 0;
}
注意:
友元提供了一种突破封装的方式,有时候提供了便利。但是友元一定程度上破坏封装性,所以不宜多用。
现在我们尝试一段代码去重载operator<<,然后发现我们没办法将operator<<重载成成员函数。原因是cout的输出流对象和隐含的this指针在抢占第一个参数的位置。
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{
}
ostream& operator<<(ostream& out)
{
out << d._year << "-" << d._month << "-" << d._day;
return out;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2021, 3, 9);
cout << d;
return 0;
}
这里要用到友元函数来解决这个问题!!!
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
class Date
{
friend ostream& operator<<(ostream& out, const Date& d);
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{
}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "-" << d._month << "-" << d._day;
return out;
}
int main()
{
Date d(2021, 3, 9);
cout << d << endl;
return 0;
}
友元函数可访问类的私有和保护成员,但不是类的成员函数。
友元函数不能用const修饰。
友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
一个函数可以是多个类的友元函数。
友元函数的调用与普通函数的调用和原理相同。
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
但是注意:
class Date; // 前置声明
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成
员变量
public:
Time(int hour, int minute, int second)
: _hour(hour)
, _minute(minute)
, _second(second)
{
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{
}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问时间类私有的成员变量
_t._hour = hour;
_t._minute = minute;
_t.second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
上述代码中声明了Date类为Time类的友元类,则Date类可以直接访问Time类的私有成员变量,但是Time类不能访问Date类。