一、友元
友元可以允许其他类或者函数访问自己的非共有成员,如果类想把它的函数作为友元,只需要增加一条以friend开头的函数声明即可。
1.1 添加外部函数作为友元
以下一个学生类,类中保存了学生的年龄、名字以及性别信息:
class stu_st {
private:
int age;
string name;
char sex;
};
现在希望在类外面以函数的形式来计算两个学生的年龄之和,因为age
成员是私有的,所以目前类外部的函数是无法获取到学生年龄,这个想法无法完成。但是有了友元之后,这个想法就能实现了。只要在类中添加友元定义,外部再实现函数就可以了:
class stu_st {
friend int figure_age(const stu_st &a, const stu_st &b);
// ...
};
// 实现计算年龄函数
int figure_age(const stu_st &a, const stu_st &b) {
return a.age + b.age;
}
友元是不区分共有和私有的,以友元修饰的函数即使声明在private域,外部也是能访问的。
1.2 以外部类作为友元
新增一个老师类,老师能获取学生的年龄:
class teacher_st;
class stu_st {
friend class teacher_st;
// ...
};
class teacher_st {
public:
unsigned int get_stu_age(const stu_st &stu) {
return stu.age;
}
};
1.3 静态成员变量
当类中存在静态变量时,友元类和函数也是能直接访问这个变量的。
以下代码声明了一个teacher_st
作为老师类,声明了一个stu_st
作为学生类,学生类中有一个静态变量total_count
表示学生的总数,老师作为友元类来获取这个数量:
#include <iostream>
using namespace std;
class teacher_st;
class stu_st {
friend class teacher_st;
private:
static unsigned int total_count;
};
class teacher_st {
public:
unsigned int get_stu_count() {
return stu_st::total_count;
}
};
unsigned int stu_st::total_count = 10;
int main() {
teacher_st t;
cout << t.get_stu_count() << endl;
return 0;
}
运行结果:
二、运算符重载
2.1 运算符重载语法
运算符重载给类提供了大大的便利性,使得自定义类型也能和内置类型一样使用系统操作符。
运算符重载的语法:
void operator+(const stu_st &s);
各元素说明:
void
:返回值类型operator+
:表示重载运算符+
s
:运算符的参数
运算符重载有几种不同的写法,可以写在类中,也可以写在类外面。
在类中声明
以学生类为例,重载小于符号<
使得类可以直接通过年龄大小作为对比:
class stu_st {
private:
unsigned int age;
string name;
public:
stu_st(int age, string name) : age(age), name(name) {
}
// 重载小于符号
bool operator<(const stu_st &x) const {
return this->age < x.age;
}
};
在类外面声明
因为类外面的函数无法直接访问类内部数据,因此,类外面的函数需要被声明为类的友元函数。
class stu_st {
private:
unsigned int age;
string name;
public:
// 声明重载操作符>
friend bool operator>(const stu_st &, const stu_st &);
};
bool operator>(const stu_st &a, const stu_st &b) {
return a.age > b.age;
}
注意
在类内部重载操作符,编译器默认会把this作为第一个参数传入,因此,重载时无需再传入当前类对象本身。例如:
bool operator<(const stu_st &x) const
这就表示用当前对象和x对象作对比。而外部声明的函数,因为没有封装在类中,不能传入this指针,因此声明时需要传入对象本身。即:
friend bool operator>(const stu_st &, const stu_st &);
2.3 重载输入输出运算符
重载输入和输出运算符需要注意的一个问题是:与iostream标准库相关的运算符重载,必须是非成员函数。
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class stu_st {
private:
unsigned int age;
string name;
public:
stu_st() {};
friend istream &operator>>(istream &, stu_st &);
friend ostream &operator<<(ostream &os, const stu_st &stu);
};
// 重载输出运算符
ostream &operator<<(ostream &os, const stu_st &stu) {
os << "Name: " << stu.name << "\tAge: " << stu.age;
return os;
}
// 重载输入运算符
istream &operator>>(istream &is, stu_st &stu) {
is >> stu.name >> stu.age;
return is;
}
int main() {
stu_st stu;
cin >> stu;
cout << stu;
}
测试效果:
此处评论已关闭