c++初阶------类和对象(六大默认构造函数的揭破)-2
https://developer.aliyun.com/article/1499147
cout的流提取(<<)
小解释
我们在使用std::cout的打印不同类型是不需要和C语言写出格式符,
我们使用iostram头文件,主要就是里面定义了对象,
我们顺着点击
就会看到下图
可以看到定义了很多函数,简单的来说就是函数重载,类型匹配,进而就解释了cout支持流提取,cout是一个对象,
那我们来函数重载一个流提取
void Date::operator<<(ostream& out) { out << _year << "-" << _month << "-" << _day << endl; }
out相当于我们把std::cou传入,
cout的小例子
我们有时候在使用cout打印一个自定义类型的变量时,会出错,例如
Date A;//Date是一个类,A是对象 cout<<A;
如果我们这样写的话会报错,因为cout的类方法是没有写这样的双操作数运算符符重载的,
如果我们按照刚刚写的日期类的流提取的函数重载,
可以这样
这样可以正常输出,因为双操作数运算符的第一个参数是左操作数,第二个参数是右操作数,我们这个日期类的流提取函数重载的第一个参数就是this这个隐藏的参数
void Date::operator<<(Date * const this ,ostream& out)
这样实现的话虽然没有错,但是不方便理解,运算符重载也没有规定在类之外不能进行重载,所以我们可以在类外进行运算符重载
void operator<<(ostream& out, const Date& A) { out << A._year << "-" << A._month << "-" << A._day << endl; }
需要把Date的类成员进行public权限才能成功运行
友元函数
或者我们可以写一个友元函数
友元函数 :既可以是不属于任何类的非成员函数,也可以是另一个类的成员函数 ,统称为友元函数
//友元函数 friend void operator<<(ostream& out, const Date& A) { out << A._year << "-" << A._month << "-" << A._day << endl; }
这个函数是在类定义的,但是不是成员函数,
如果在类之外定义不用加Data::这个
我们还知道
cout << a<< b<<endl;
支持这样的上面写的不支持,如果要改动,就把返回类型改为ostream&
这样就可以支持了
流插入
//流插入 friend istream& operator>>(istream& out, Date& A) { out >> A._year; out >> A._month; out >> A._day; cout << A; return out; }
小总结
一般的运算符一般实现成成员函数,而流插入和流提取必须实现全局,这样才能让流对象作为第一个参数.
流是为解决自定义类型的输入和输出问题,C语言的printf 、scanf只能解决内置类型,无法解决自定义类型的输入输出问题
const成员函数
我们在C语言知道,const修饰的变量是改变不了,如果是强行改变那就另当别论了,需要注意的是权限可以平移和缩小,但是不能放大,也就是说,const修饰的变量可以传参给const修饰的变量(权限平移), 非const修饰的变量可以传参给const修饰的变量(权限缩小), 但是不能const修饰的变量可以传参给非const修饰的变量(权限放大)
那么在cpp中是怎么使用const,会有怎么样的效果呢?
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
这里我定义一个const修饰的对象,一个是没有const修饰的对象,
当我们写出下面代码
会发现有报错,为啥会这样呢
在这个运算符重载中,this这个参数是没有被const修饰过的,被const修饰过的A使用没有被const的成员函数,就会报错,
所以这里有个结论:
- const对象,不能调用非const成员函数,只能调用const成员函数(权限的平移)
- 普通对象可以调用非const成员函数,也可以调用const成员函数(权限的平移和缩小)
取地址及const取地址操作符重载
//取地址操作符重载 Date* Date::operator&() { return this; } //主要为了适应const对象取地址操作符重载, const Date* Date::operator&()const { return this; }
这两个是默认成员函数一般不用重新定义 ,编译器默认会生成。
除非因为自己有想法,可以进行重载,这样可以恶搞一下其他人