本篇核心知识:友元(友元函数、友元类)、运算符重载(规则、成员 / 全局重载、特殊运算符)、重载限制、前置 / 后置自增拓展
一、友元(friend)
概念
友元是 C++打破封装 的机制,允许外部函数 / 类 访问当前类的私有、保护成员 ,是单向、不可传递、不可继承的特殊关系。
特性
1. 友元函数
-
定义:用
friend声明的全局函数,不属于任何类。 -
权限:可直接访问类的private/protected成员。
-
特点:单向授权,不改变原函数属性,仅新增访问权限。
2. 友元类
-
定义:用
friend class 类名声明的类。 -
权限:友元类的所有成员函数可访问当前类私有成员。
-
特点:单向关系 、不可传递 、不可继承。
3. 友元关系规则
-
单向:A 友元 B,B 不一定友元 A。
-
不可传递:A 友元 B、B 友元 C,A≠友元 C。
-
不可继承:子类不继承父类的友元关系。
-
声明位置:可放在任意权限区(public/private/protected),不影响权限。
代码示例
1. 友元函数
#include <iostream>
using namespace std;
class Beta {
private:
int num;
public:
Beta(int n) : num(n) {}
// 声明全局函数为友元
friend void up(Beta& b);
};
// 友元函数:访问私有成员
void up(Beta& b) {
b.num *= 10;
cout << b.num << endl;
}
int main() {
Beta b(5);
up(b); // 输出50
return 0;
}
2. 友元类
class XiaoShu {
private:
int n;
public:
XiaoShu(int x) : n(x) {}
// 声明XiaoMei为友元类
friend class XiaoMei;
};
class XiaoMei {
public:
void show(XiaoShu& s) {
cout << s.n << endl; // 访问私有成员
}
};
相似概念比较:友元 vs 成员函数
-
友元:外部授权,非类成员,单向访问。
-
成员函数:类内置,默认访问私有成员,双向绑定。
二、运算符重载
概念
运算符重载是函数重载的特殊形式,为自定义类型赋予运算符新功能,语法不变、逻辑自定义。
特性
1. 重载核心规则(必考)
-
不改变优先级、结合性、操作数个数。
-
不创造新运算符,仅扩展已有运算符功能。
-
不改变原有语义(如 + 不做减法)。
-
不能重载:
.、.*、::、?:、sizeof。 -
重载形式:成员函数 、全局函数(常配合友元)。
2. 成员函数重载
-
格式:
返回值 operator运算符(参数)。 -
特点:隐含 this 指针,第一个操作数为当前对象。
-
适用:双目运算符(+、-、*)、单目运算符、下标
[]、函数调用()、箭头->。
3. 全局函数重载
-
格式:
返回值 operator运算符(参数1, 参数2)。 -
特点:无 this 指针,需显式传所有操作数,常声明为友元访问私有成员。
-
适用:流运算符
<</>>、单目运算符、对称双目运算符。
代码示例
1. 复数加法重载(成员函数)
#include <iostream>
using namespace std;
class Complex {
private:
double real; // 实部
double imag; // 虚部
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 成员函数重载+
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
void show() const {
cout << real << "+" << imag << "i" << endl;
}
};
int main() {
Complex c1(3,4), c2(1,2);
Complex c3 = c1 + c2; // 调用重载+
c3.show(); // 输出4+6i
return 0;
}
2. 流运算符重载(全局 + 友元)
class Complex {
private:
double real, imag;
public:
Complex(double r=0, double i=0) : real(r), imag(i) {}
// 声明全局函数为友元
friend ostream& operator<<(ostream& os, const Complex& c);
};
// 全局重载<<
ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << "+" << c.imag << "i";
return os;
}
int main() {
Complex c(2,3);
cout << c << endl; // 输出2+3i
return 0;
}
三、特殊运算符重载要求
1. 必须成员函数重载
-
下标
[]、函数调用()、箭头->、赋值=。 -
原因:需通过 this 指针访问对象状态,全局无 this。
2. 必须全局函数重载
-
流运算符
<</>>、类型转换运算符。 -
原因:左操作数为流对象(非自定义类型),无法作为 this。
3. 赋值运算符(=)
-
必须成员重载,避免浅拷贝导致内存泄漏。
-
默认赋值:逐字节浅拷贝,含指针时需手动深拷贝。
四、前置 / 后置自增重载(拓展)
-
前置
++x:先增后用,无额外参数,返回引用。 -
后置
x++:先用后增 ,需加int占位参数,返回值。
代码示例
class Num {
private:
int val;
public:
Num(int v) : val(v) {}
// 前置++
Num& operator++() {
val++;
return *this;
}
// 后置++(int占位)
Num operator++(int) {
Num temp = *this;
val++;
return temp;
}
};
拓展:重载 new/delete
-
禁止重载全局
new/delete,仅重载类专属版本。 -
重载中不可直接调用 new/delete ,避免递归,改用
malloc/free。