C++11新增
初始化方面
C++11允许非静态成员变量在类内声明时直接进行初始化
class B
{
public:
void print()
{
cout << _a << _b << _c << endl;
}
private:
int _a = 10;
char _b = 'A';
double _c = 1.1;
};
int main()
{
B b1, b2;
b1.print();
b2.print();
return 0;
}
打印结果为:
这说明普通成员变量可以在声明时进行初始化。
class A
{
private:
int _c = 10;
};
class B
{
public:
void print()
{
cout << _a << endl;
}
private:
static int _a = 1;//静态成员变量error!
A a;
};
报出的错误如下:
友元
友元提供了一种突破封装的方式,有时候可以给用户提供便利,但是友元函数同时也破坏了封装,所以友元在类中不宜多用。
友元分为友元函数和友元类
友元函数
在日期类中进行输出运算符重载的时候,会遇到如下的麻烦事?
class Date
{
public:
Date(int year = 2019, int month = 10, int day = 23)
: _year(year)
, _month(month)
, _day(day)
{}
ostream& operator<<(ostream& cout)//输出运算符的重载
{
cout << _year << _month << _day << endl;
return cout;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d;
d << cout;//奇怪的调用方式
return 0;
}
我们发现,由于"<<"该运算符的类内重载时左右操作数的问题(由于成员函数包含this指针,并且在参数列表中的首位(在之前的this节已经证明过)),this指针变成了左操作数,所以导致输出运算符重载的调用方式与大众不同,所以,为了避免this指针带来的问题,可以引入友元函数来进行解决。
class Date
{
public:
friend ostream& operator<<(ostream& cout, const Date& d);
Date(int year = 2019, int month = 10, int day = 23)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& cout, const Date& d)
{
cout << d._year << d._month << d._day << endl;
return cout;
}
int main()
{
Date d;
//d << cout;
cout << d;//这样就正常多了
return 0;
}
?通过调用类的友元函数,完成了将输出运算符重载的正确格式。
友元函数特性
- 可以直接访问类内私有成员(与该类交了朋友)声明在类外定义在类内的普通函数并非类内成员函数,声明是需要加上friend关键字,不属于任何类。
- 友元函数不能用const来修饰。
- 一个函数可以是多个类的友元函数。
- 友元函数的调用与普通成员函数的调用和原理相同。
友元类
类与类至今进行交朋友,但是这种朋友是单向的,即:你可以把我认为是你的朋友,可以用(访问)你的东西(非公有成员变量),但是,我并没把你认为是我的朋友,所以我的东西也不给你用
class Date
{
friend class Time;
//意思是,我Date类中的所有变量,给你Time类用。
//...
};
可以参考一下代码?
class B
{
friend class A;//声明A为B的友元,意为B中的成员变量可供A访问
public:
B()
{
_b1 = 10;
_b2 = 20;
}
private:
int _b1;
int _b2;
};
class A
{
public:
void print()
{
cout << "B::_b1 = " << _b._b1 << endl;//访问B中的私有成员变量
cout << "B::_b2 = " << _b._b2 << endl;
cout << "A::_a = " << _a << endl;
}
private:
int _a = 100;
B _b;//创建A类中的B对象
};
int main()
{
A a;
a.print();
return 0;
}
不难看出,A类实例化的对象a可以访问B类中的私有成员变量。
上述代码的友元关系是,在B中定义了B是A的友元,即为B中的成员变量A可以访问,不受限制
class B
{
friend class A;
public:
B()
{
_b1 = 10;
_b2 = 20;
}
void print()
{
cout << "A::_a = " << a._a << endl;//error!B类试图访问A类中的私有成员变量
}
private:
int _b1;
int _b2;
A a;
};
class A
{
public:
private:
int _a = 100;
};
int main()
{
B b;
b.print();
return 0;
}
直接给用户报出一个错误:
报出A中的_a时不可访问的。
友元类特性
- 友元关系是单行的,不具有交换性(A类为B类的友元,但是B类可以不为A类的友元)
- 友元关系不具有传递性如果B是A的友元,C是B的友元,但不能说明C是A的友元
内部类
概念:如果一个类定义在另一个类的内部,这个类就叫做内部类。
内部类特性
- 内部类是外部类的友元类,即在内部类中的定义的外部类对象可以在内部类中调用外部类的私有成员变量。
- 外部类不可以访问任何内部类中的私有成员。
- 内部类可以定义在外部类的任何一位置, 但是访问权限不受位置影响。
- 内部类可以直接访问外部类中的static、枚举成员,不需要加外部类的访问限定符。
- sizeof(外部类)的大小与内部类的大小无关。
class A
{
public:
class B
{
public:
void print(const A& a)
{
cout << _sa << endl;//访问外部类中的static成员变量
cout << a._a << endl;//通过a对象来调用A类私有成员变量
}
private:
int _b;
static int _sb;
};
private:
int _a = 0;
static int _sa;
};
int A::B::_sb = 10;//static初始化方式
int A::_sa = 20;
类和对象完结~ending