构造函数初始化
(一)初始化列表:以冒号开始,逗号分隔的数据成员列表。数据成员后面括号写初始值或表达式。
class Date {
//构造函数
public:
Date(int year, int month, int day)
:_year(year) ,
_month(month),
_day(day)
{}
private:
int _year;
int _month;
int _day;
};
每个成员变量在初始化列表中只能出现一次。
对于成员变量初始化,在构造函数中直接赋值,为什么还要写初始化列表?因为初始化只能初始化一次,而构造函数体内可以多次赋值。在类中包含以下成员,必须放在初始化列表位置进行初始化。
(1)引用成员变量
class A
{
public:
A(int a)
:_a(a)
{
cout << "A(int a)" << endl;
}
private:
int _a;
int& _ret;
};
(2)const成员变量
class A
{
public:
A(int a,int ref)
:_a(a),
_ret(ref)
{
cout << "A(int a)" << endl;
}
private:
int _a;
int& _ret;
const int _b;
};
(3)自定义类型成员(且该类没有默认构造函数)
class B {
public:
B(int b)
:_c(5)
{
cout << "B()" << endl;
}
private:
int _c;
};
class A
{
public:
A(int a,int ref,int c)
:_a(a),
_ret(ref),
_b(5)
{
cout << "A(int a)" << endl;
}
private:
int _a;
int& _ret;
const int _b;
B aa;
};
(二)尽量使用初始化列表,无论是否使用初始化列表,对于自定义类型的成员变量,一定会使用成员列表进行初始化。
(三)成员变量在类中声明的次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的次序无关。
class A {
public:
A(int a)
:_a1(a),
_a2(_a1)
{}
void Print() {
cout << _a1 << " " << _a2 << endl;
}
private:
int _a2;
int _a1;
};
int main() {
A aa(1);
aa.Print();
return 0;
}
先声明a2,所以先初始化a2,将a1赋值给a2,此时a1是随机值,所以a2是随机值。再声明a1,将a赋值给a1,所以a1是1。
static成员
(一)概念
类的静态成员:static的类成员用
静态成员变量:static修饰的成员变量
静态成员函数:static修饰的成员函数
静态成员变量一定要在类外进行初始化。
class A {
public:
A(int a=0) {
count++;
cout << "A(int a=0)" << endl;
}
A(const A& a) {
count++;
cout << "A(const A& a)" << endl;
}
static int GetCount() {
//_a++; 错误的,不能访问非静态成员
return count;
}
private:
static int count; //声明
int _a;
};
int A::count= 0; //在类外定义初始化
int main() {
A aa;
cout << A::GetCount() << endl;
cout << aa.GetCount() << endl;
}
(二)静态成员特性
- 静态成员为所有类成员对象共享,不属于某个具体的对象,存放在静态区。
- 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
- 类静态成员用类名::静态成员或者对象.静态成员来访问。
- 静态成员函数中没有隐藏的this指针,不能访问非静态成员。
- 静态成员也是类的成员,受public,protected,private访问限定符的限制。
友元
友元函数
友元函数直接访问类的私有成员,它是定义在类外部的普通函数,但在类的内部要声明,声明时需要加上friend关键字。
//输入,输出类
class Date
{
friend istream& operator>>(istream& cin, Date& d);
friend ostream& operator<<(ostream& cout, const Date& d);
public:
Date(int year=2023,int month=2, int day=2)
:_year(year),
_month(month),
_day(day)
{}
private:
int _year;
int _month;
int _day;
};
//输入
istream& operator>>(istream& cin, Date& d) {
cin >> d._year;
cin >> d._month;
cin >> d._day;
return cin;
}
//输出
ostream& operator<<(ostream& cout, const Date& d) {
cout << d._year << "年" << d._month << "月" << d._day << "日";
return cout;
}
int main() {
Date d;
cin >> d;
cout << d << endl;
return 0;
}
- 友元函数可以访问类的私有成员,但不是类的成员函数。
- 友元函数不能用const修饰。
- 友元函数可以在类的任何地方声明,不受访问限定符的限制。
- 一个函数可以是多个类的友元函数。
友元类
友元类的所有成员函数都可以是另一个类的成员函数,都可以访问另一个类的非公有成员。
class Date
{
friend class Time;
public:
Date(int year = 2023, int month = 2, int day = 2)
:_year(year),
_month(month),
_day(day)
{}
private:
int _year;
int _month;
int _day;
};
class Time
{
public:
Time(int hour = 0, int minute = 0, int second = 0)
:_hour(hour),
_minute(minute),
_second(second)
{}
void SetDateOfTime(int year, int month, int day) {
_t._year = year;
_t._month = month;
_t._day = day;
}
private:
int _hour;
int _minute;
int _second;
Date _t;
};
在Date类中声明Time为其友元类,那么在Time类中直接访问Date类的私有成员变量,但Date类中访问Time类的私有成员变量不可以。
匿名对象
class A
{
public:
A(int a=10)
:_a(a)
{}
void Print() {
cout << _a << endl;
}
private:
int _a;
};
int main() {
A(); //生成一个匿名对象,生命周期只有这一行
A aa(20);
A ret = A(20);
//首先生成一个匿名对象,将匿名对象变为ret对象
//生命周期是ret的生命周期
A().Print();
return 0;
}