文章目录
- 重载operator<< 输出自定义类型
- const对象 无法调用 非const成员函数
- 非const函数的缺陷
- 初始化列表:==对象的成员定义的位置==
- 为什么会要用到初始化列表?
- 自定义类型成员如何初始列表初始化
- 灵活的初始化列表
- 声明次序
- 内置类型_size不给缺省值,仍然会走初始化列表,给了一个随机值
- 隐式类型转换与编译器优化连续构造
- static
重载operator<< 输出自定义类型
类内重载导致操作数顺序颠倒问题:
所以定义在类外,但又要访问私有成员变量,就利用友元突破访问限制
类外定义利用cout这个对象的别名,输出对象的成员变量,并且需要返回这个cout的别名,因为对于连续输出需要从左到右返回cout的顺序问题 cout<< x << y <<endl;
const对象 无法调用 非const成员函数
原因:权限可以缩小,但不能放大
结论:只要是不修改this指针指向的对象内容的成员函数,都可以加上const
好处是 非const和const的对象都可以调用,但对于要修改this指向内容的对象加上const就没法改了
非const函数的缺陷
bool operator(const Date& x) 没加const 导致d2 < d1 等价于 d2.operator(&d2,d2),此时this指针类型是const Date* 是一种权限的放大,所以结合结论,不改变成员变量的函数需要加const
初始化列表:对象的成员定义的位置
熟悉的玩法是构造体函数赋值
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,
构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值
无论怎样最终都会走到初始化列表
即使是没用初始化列表,对象的成员变量仍然会走初始化列表
为什么会要用到初始化列表?
构造体赋值无法解决 在定义的时候就得初始化的变量
特征:必须在定义的时候初始化
如:引用成员变量
const成员变量
自定义类型成员(且该类没有默认构造函数时)(也必须在定义时初始化,因为需要传参)(如果有默认构造函数,就不需要传参,初始化列表可以初始化,也可以不初始化,不初始化就自动调用默认构造函数,就看你想不想显示初始化了)
自定义类型成员如何初始列表初始化
灵活的初始化列表
不写初始化列表,所有的成员也会走初始化列表,因为初始化列表是成员定义的地方,它至少会出现一次,则_pushst和_popst就去调用它们的默认构造,如果想显示的初始化对象同样也可以在初始化列表里面传参去初始化
声明次序
成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
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();
}
A. 输出1 1
B.程序崩溃
C.编译不通过
D.输出1 随机值
初始化顺序:
private:
int _a2;
int _a1;
先初始化_a2,再_a1,导致_a2是个随机值
内置类型_size不给缺省值,仍然会走初始化列表,给了一个随机值
隐式类型转换与编译器优化连续构造
A aa2 = 2; 发生隐式类型转换,2作为参数传给构造函数,构造成临时变量是A类型,再拷贝构造给A aa2
但是连续的构造会被编译器优化成用2直接构造
类比 double 和 int 的临时变量
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
:_a(a)
{
cout << "A(int a)" << endl;
}
A(const A& aa)
:_a(aa._a)
{
cout << "A(const A& aa)" << endl;
}
private:
int _a;
};
int main()
{
A aa1(1);
A aa2 = 2;
return 0;
}