C++(3)

三、运算符重载

1、友元(熟悉)

1.1 概念

类通过私有成员实现数据封装,但某些场景下频繁访问私有成员会导致效率问题。友元机制允许特定函数/类访问私有成员,但会破坏封装性,需谨慎使用。

​友元实现方式​​:

  • 友元函数
  • 友元类
  • 友元成员函数

1.2 友元函数

友元函数是类外定义的普通函数,需在类内用friend声明。

​特点​​:

  • this指针
  • 声明位置不受访问权限限制
  • 可访问多个类的私有成员(需在各自类中声明)
示例代码
复制代码
#include <iostream>
using namespace std;

class Test {
private:
    int a;
public:
    Test(int i) : a(i) {}
    void show() { cout<< a << " " << &a << endl; }
    
    // 友元函数声明
    friend void and_test(Test &t);
};

// 友元函数定义
void and_test(Test &t) {
    cout << t.a << " " << &t.a << endl;
}

int main() {
    Test t1(1);
    and_test(t1); // 输出与成员函数相同
    t1.show();
    return 0;
}

1.3 友元类

若类B是类A的友元类,则B可访问A的所有成员。

​特性​​:

  • 友元关系不可继承
  • 不具有交换性(需双向声明)
互为友元示例
复制代码
class Cat; // 前向声明

class Test {
private:
    int a;
public:
    Test(int i) : a(i) {}
    void test(Cat &c);
    friend class Cat; // 声明Cat为友元类
};

class Cat {
private:
    int b;
public:
    Cat(int i) : b(i) {}
    void test1(Test &t) {
        cout << t.a++ << endl; // 访问Test私有成员
    }
    friend class Test; // 双向友元
};

void Test::test(Cat &c) {
    cout << c.b << endl; // 访问Cat私有成员
}

int main() {
    Test t(44);
    Cat c(12);
    c.test1(t); // 输出45(Test的a自增)
    return 0;
}

1.4 友元成员函数

使类B的特定成员函数成为类A的友元,可访问A的私有成员。

​实现步骤​​:

  1. 前向声明目标类
  2. 在目标类中声明友元成员函数
  3. 定义成员函数时需指定类作用域
示例代码
复制代码
class Test; // 前向声明

class B {
public:
    void and_test(Test &t); // 声明友元成员函数
};

class Test {
private:
    int a;
public:
    Test(int i) : a(i) {}
    friend void B::and_test(Test &t); // 声明友元成员函数
};

void B::and_test(Test &t) {
    cout << t.a << endl; // 访问Test私有成员
}

int main() {
    Test t1(2);
    B b;
    b.and_test(t1); // 输出2
    return 0;
}

2、运算符重载(掌握)

2.1 概念

允许为自定义类型重载运算符,使其支持类似内置类型的操作。

​实现方式​​:

  • 友元函数重载
  • 成员函数重载

2.2 友元函数运算符重载

适用于需要对称性的操作(如二元运算符)。

示例:+运算符
复制代码
class MyInt {
private:
    int a;
public:
    MyInt(int a) : a(a) {}
    friend MyInt operator+(MyInt &i, MyInt &i2); // 友元声明
};

MyInt operator+(MyInt &i, MyInt &i2) {
    return MyInt(i.a + i2.a); // 隐式调用构造函数
}
示例:++运算符
复制代码
class MyInt {
    // ...
    friend MyInt operator++(MyInt &i);      // 前置++
    friend MyInt operator++(MyInt &i, int); // 后置++
};

MyInt operator++(MyInt &i) { return ++i.a; }         // 前置
MyInt operator++(MyInt &i, int) { return i.a++; }    // 后置

2.3 成员函数运算符重载

隐含this作为左操作数,适用于非对称操作。

示例:+运算符
复制代码
class MyInt {
public:
    MyInt operator+(MyInt &i2) {
        return MyInt(this->a + i2.a);
    }
};

2.4 特殊运算符重载

2.4.1 赋值运算符重载

默认生成浅拷贝,需手动实现深拷贝。

复制代码
class MyInt {
public:
    MyInt& operator=(MyInt &i) {
        if (this != &i) this->a = i.a;
        return *this;
    }
};
2.4.2 类型转换运算符重载

必须为成员函数,返回目标类型。

复制代码
class MyInt {
public:
    operator int() { return a; }       // 转int
    operator string() { return "hello"; } // 转string
};

2.5 注意事项

  1. 不可创建新运算符
  2. 不支持默认参数
  3. 不改变优先级和结合性
  4. 建议:双目用友元,单目用成员

3、std::string 字符串类

核心操作示例
复制代码
string s1 = "hello";
string s2("world");

// 拼接与追加
s1 += s2;          // s1 = "helloworld"
s1.append("!!!");    // s1 = "helloworld!!!"

// 插入与删除
s1.insert(5, " ");   // s1 = "hello world"
s1.erase(5, 6);      // s1 = "hello"

// 替换与清空
s1.replace(0, 5, "Hi"); // s1 = "Hi"
s1.clear();

// C风格转换
char arr[10];
strcpy(arr, s1.c_str()); // C字符串转换
相关推荐
十年编程老舅8 分钟前
‌C++左值与右值:从基础概念到核心应用‌
linux·c++·右值引用·c++17·c++左值·c++右值·左值引用
John_ToDebug20 分钟前
Chrome性能黑魔法:深入浅出PGO优化与实战指南
c++·chrome
我叫汪枫25 分钟前
C语言深度入门系列:第十一篇 - 动态内存管理与数据结构:程序世界的高效算法大师
c语言·数据结构·算法
空山新雨(大队长)28 分钟前
Java第五课:输入输出
java·开发语言
Li_76953229 分钟前
优选算法100 题 ——1 双指针
算法
77qqqiqi32 分钟前
算法——数学基础
算法
啊?啊?33 分钟前
7 排序算法通关指南:从 O (n²)(选择 / 冒泡)到 O (nlogn)(快排 / 归并)+ 计数排序
数据结构·算法·排序算法
张较瘦_36 分钟前
[论文阅读] 算法 | 抗量子+紧凑!SM3-OTS:基于国产哈希算法的一次签名新方案
论文阅读·算法·哈希算法
芒克芒克37 分钟前
LeetCode 面试经典 150 题:多数元素(摩尔投票法详解 + 多解法对比)
算法·leetcode·面试
wow_DG38 分钟前
【Vue2 ✨】Vue2 入门之旅 · 进阶篇(二):虚拟 DOM 与 Diff 算法
开发语言·javascript·vue.js·算法·前端框架