C++ Primer Plus 第十一章知识点简化
1. 类的运算符重载
对于重载(多态)之前也提到过,这一部分主要是讲述类的重载以及注意点。
#ifndef TIME_H_
#define TIME_H_
class Time{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = 0, int m = 0);
const Time Sum(const Time& t) const;
Time operator+(const Time& t) const;
void Show() const;
};
#endif
#include <iostream>
#include "time.h"
Time::Time(){
hours = minutes = 0;
}
Time::Time(int h, int m){
hours = h;
minutes = m;
}
void Time::AddMin(int m){
minutes += m;
hours += minutes / 60;
minutes %= 60;
}
void Time::AddHr(int h){
hours += h;
}
void Time::Reset(int h, int m){
hours = h;
minutes = m;
}
const Time Time::Sum(const Time& t) const{
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
void Time::Show() const{
std::cout << hours << " hours, " << minutes << " minutes";
}
Time Time::operator+(const Time& t) const{
Time temp;
temp.minutes = (minutes + t.minutes) % 60;
temp.hours = hours + t.hours + (minutes + t.minutes) / 60;
return temp;
}
#include <iostream>
#include "time.h"
using namespace std;
int main(){
Time planning, total_1, total_2;
Time coding(2, 40);
Time fixing(5, 55);
cout << "planning time = ";
planning.Show();
cout << endl;
cout << "coding time = ";
coding.Show();
cout << endl;
cout << "fixing time = ";
fixing.Show();
cout << endl;
total_1 = coding.Sum(fixing);
total_1.Show();
cout << endl;
total_2 = coding + fixing;
total_2.Show();
cout << endl;
return 0;
}
注意点:
- 切记一定不能返回指向局部变量的引用,可以返回局部变量但不能是引用;
- 运算符重载有限制,见书 P387。
2. 友元
归纳点:
- 创建友元,只需在类声明里加关键字
friend
;- 默认构造函数和非默认构造函数;
- 析构函数。
对于类的私有数据成员的访问,除了类的成员函数可以实现,还有别的途径吗?还有就是友元,友元有三种:
- 友元函数
- 友元类
- 友元成员函数
为什么需要友元呢?我来假设一种情况,假如有两个Time
类对象 A、B,这时候我要让B的数据成员hours
和minutes
都乘以一个常数,假定为3,最后赋值给A怎么实现?首先我们肯定会想到运算符重载,即:Time Time::operator*(const Time& t, double m) const;
,然后在主函数里写上A = B * 3.0;
,那如果写上A = 3.0 * B;
会怎么样?会报错,因为3.0不是Time类,那怎么解决呢?
只能需要非成员函数来实现,即:
Time operator*(double m,const Time& t) const{
Time temp;
temp.hours = m * t.hours;
temp.minutes = m * t.minutes;
return temp;
}
写完你就会发现,非成员函数不让访问类的私有数据成员,这时候怎么办?友元函数可以做到,只需在类里面添加一个类声明friend Time operator*(double m,const Time& t) const;
3. 友元的拓展
先来看两段代码,然后我抛出一些问题来思考:
① Demo1
class Time{
private:
int hours;
int minutes;
public:
//...;
friend void operator<<(ostream& os, const Time& t);
};
void operator<<(ostream& os, const Time& t){
os << t.hours << t.minutes << endl;
}
问题:operator<<()是Time类的友元函数,但该函数不是ostream类的友元,这会报错吗?
首先想想什么时候用到友元函数,为什么要用?因为需要访问私有成员,上面函数访问了Time类的私有数据成员
hours
和minutes
,有访问ostream类的吗?没有就不用声明为ostream类的友元函数。
② Demo2
class Time{
private:
int hours;
int minutes;
public:
//...;
friend ostream& operator<<(ostream& os, const Time& t);
};
ostream& operator<<(ostream& os, const Time& t){
os << t.hours << t.minutes << endl;
return os;
}
问题:operator<<(ostream& os, const Time& t)写好后,实参怎么写?
这部分和demo1实现功能一模一样。两种写法而已。那实参怎么写?直接参考operator+(Time& o, const Time& t)的实参就是
A + B
,那这个就是cout << A
,除了这么写还可以这样:#include<fstream> int main(){ ofstream fout; fout.open("demo.txt"); Time A(10, 50); fout << A; // 重载<< }
Reference:
- 《C++ Primer Plus》第六版 Stephen Prata 著