一、权限的放大
权限的放大:在指针和引用赋值中,权限可以缩小,但不可以放大:这里通常指的是变量的值可不可以改的问题,如果说是从改到不能改,这就是将权限缩小了,这是可行的;如果说是从不能改到能改,这就是权限放大了,此时是不行的。
class A
{
public:
//const 修饰 *this
//this的类型变成const A*
void Print()
{
cout << _a << endl;
}
A* operator&()
{
return this;
}
private:
int _a=10;
};
解决方案:在函数后加const
例如:
class A
{
public:
//const 修饰 *this
//this的类型变成const A*
void Print() const
{
cout << _a << endl;
}
A* operator&()
{
return this;
}
private:
int _a=10;
};
一张图说明:
二、初始化列表
【注意】
- 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
- 类中包含以下成员,必须放在初始化列表位置进行初始化:
引用成员变量
const成员变量
自定义类型成员(且该类没有默认构造函数时)
代码如下(示例):
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B(int a, int ref)
:_aobj(a)
,_ref(ref)
,_n(10)
{}
private:
A _aobj; // 没有默认构造函数
int& _ref; // 引用
const int _n; // const
};
- 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
- 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
代码如下(示例):
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();
}
运行结果:
调换一下声明顺序的运行结果:
三、流输入/流输出重载
代码如下(示例):
类内声明:
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
friend:意为友元函数,在类外定义,可以访问类的私有成员。
类内定义:
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
运行效果: