C++~02运算符重载

1.友元

类: 实现对数据的隐藏和封装,类中的数据成员一般定义为私有类型,这样的情况下类内通过成员函数才能够读取。

友元: 是一种允许非成员函数或者非当前类的成员函数访问一个类的私有成员的一种机制,破坏封装的特性。

友元的实现方式:

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

1.1 友元函数

友元函数不属于任何一个类,是类外的一个函数,但是可以访问类内的私有成员。

友元函数需要类内"声明",类外定义。

例:客厅 卧室

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Room
{
private:
    string bed_room="$$$$$$$$$$";
public:
    string living_room="*****";
    //  声明友元函数
    friend void fun(Room & r);
};

void fun(Room & r)
{
    cout << r.living_room << endl;
    cout << r.bed_room << endl;
}
int main()
{
    Room r1;
    cout << r1.living_room << endl;
    fun(r1);

    return 0;
}
复制代码

友元函数使用需要注意:

  • 友元函数内部没有this指针
  • 友元函数的声明可以放置在类的任何位置,不受权限修饰符的影响
  • 一个友元函数理论上可以访问多个类,分类在每一个类中进行声明

1.2 友元类

当一个类B成为了另一个类Test的"好朋友"时,类test中的所有成员都可以被类B访问,此时类B就是类Test的友元类。

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    void fun()
    {
       cout << a << endl;
    }
    // 声明友元类
    friend class B;
};

class B
{
public :
    void test_print(Test & t)
    {
        cout << t.a << endl;
    }
    void test_a(Test & t)
    {
        cout << t.a << endl;
    }
};
int main()
{
    Test t1(10);
    t1.fun (); // 10
    B b1;
    b1.test_print (t1); // 10
    b1.test_a (t1); // 10

    return 0;
}

友元类使用的时候需要注意:

  • 友元关系不能继承
  • 友元关系不具有交换性
  • 友元关系不具有传递性

1.3 友元成员函数

使类B中的成员函数称为类Test的友元成员函数,这样类B的该成员函数就是类Test的友元成员函数,也就可以访问类Test的所有成员

步骤:

  1. 在Test类中声明友元成员函数
  2. 成员函数在类外进行定义
  3. 在类B中声明此成员函数
  4. 在类B之前声明类Test
cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
// 4.在类B之前声明类Test
class Test;
class B
{
public:
    // 3.在类B中声明此成员函数
    void test_friend(Test & t);
};

class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    void fun()
    {
        cout << a << endl;
    }
    // 1.在Test类中声明友元成员函数
    friend void B::test_friend(Test & t);
};
// 2.成员函数在类外进行定义
void B::test_friend(Test & t)
{
    cout << t.a << endl;
}

int main()
{
    Test t1(100);
    B b1;
    b1.test_friend (t1); // 100


    return 0;
}

2.运算符重载

c++中可以把部分的运算符看成是函数,此时运算符也就是可以重载。本质是函数重载

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
};
int main()
{
    Test t1(1);
    Test t2(1);
    Test t3= t1+t2; // 报错
    //    int a1=1;
    //    int b1=1;
    //    int c=a1+b1;
    cout << t3.get_a () << endl;// 2
    return 0;
}

重载的方式:

  • 友元函数运算符重载
  • 成员函数运算符重载

2.1 友元函数运算符重载

双目运算为例:+

运算符函数名:operator 符号

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
    friend Test operator +(const Test & t1,const Test & t2);
};
Test operator +(const Test & t1,const Test & t2)
{
//    Test t3;
//    t3.a = t1.a+t2.a;
//  return t1.a+t2.a;
    return Test(t1.a+t2.a);}

int main()
{
    Test t1(1);
    Test t2(1);
//    Test t4=t2;
    Test t3= t1 + t2;
    cout << t3.get_a () << endl;// 2

    return 0;
}

单目运算符:++为例

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
    friend Test operator +(const Test & t1,const Test & t2);
    friend Test operator ++(Test & t1); // 前置
    friend Test operator ++(Test & t1,int); // 后置
};
Test operator +(const Test & t1,const Test & t2)
{
//    Test t3;
//    t3.a = t1.a+t2.a;
//  return t1.a+t2.a;
    return Test(t1.a+t2.a);
}
Test operator ++(Test & t1)
{
 return ++t1.a;
}
Test operator ++(Test & t1,int)
{
   return t1.a++;
}


int main()
{
    Test t1(10);
    Test t2(1);
//    Test t4=t2;
    Test t3= t1 + t2;
    cout << t3.get_a () << endl;// 11
    cout << (++t1).get_a () << endl; // 11
    cout << (t1++).get_a () << endl; // 11

    return 0;
}

2.2 成员函数运算符重载

成员函数中有this指针,所以成员函数运算符重载可以比友元函数运算符重载少一个参数。因为this指针默认接收第一个参数。(this指针默认指向第一个参数)

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
    //    friend Test operator +(const Test & t1,const Test & t2);
    //    friend Test operator ++(Test & t1); // 前置
    //    friend Test operator ++(Test & t1,int); // 后置
    Test operator +(const Test & t2);
    Test operator ++(); // 前置
    Test operator ++(int); // 后置
};
Test Test::operator +(const Test & t2)
{
    return Test(this->a+t2.a);
}

Test Test::operator ++()
{
    return ++this->a;
}

Test Test::operator ++(int)
{
    return this->a++;
}


int main()
{
    Test t1(10);
    Test t2(1);
    //    Test t4=t2;
    Test t3= t1 + t2;
    cout << t3.get_a () << endl;// 11
    cout << (++t1).get_a () << endl; // 11
    cout << (t1++).get_a () << endl; // 11

    cout << (t1++).get_a () << endl; // 12

    return 0;
}

2.3 特殊运算符重载

部分运算符不支持友元函数运算符重载,只支持成员函数运算符重载。

2.3.1 赋值运算符重载

如果程序员不写,那么编译器会自动添加

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
// 编译器添加的运算符重载
    Test & operator =(const Test & t)
    {
        cout << "运算符" << endl;
        this->a=t.a;
        return *this;
    }

};
int main()
{
    Test t1(10);
    Test t2(1);
     t2=t1; // 调用赋值运算符重载
    Test t3(t1);// 拷贝构造函数
    Test t4=t2; // 拷贝构造函数
    return 0;
}

2.3.2 类型转换运算符重载

必须使用成员函数运算符,且格式比较特殊。

函数名:operator 要转化成的类型

不需要写返回值的类型

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int a):a(a){}
    int get_a()
    {
        return a;
    }
    // 编译器添加的运算符重载
    Test & operator =(const Test & t)
    {
        cout << "运算符" << endl;
        this->a=t.a;
        return *this;
    }
    operator int()
    {
       return this->a;
    }
    operator string()
    {
        string s="hello";
       return s;
    }
};
int main()
{
    Test t1(10);
    Test t2(1);
    t2=t1; // 调用赋值运算符重载
    int a=t1;
    string b=t1;
    cout << a << endl;// 10
    cout << b << endl;// string

    return 0;
}

注意:

  • 重载的运算符一定在c++语言中已经存在的运算符,不能创建新的运算符
  • 所以运算符重载不支持函数的默认值
  • 重载时不能改变运算符的优先级以及结合性以及语义
  • 运算符重载必须包含自定义的数据类型
  • 一般情况下,双目运算符建议使用友元函数运算符重载,单目运算符建议使用成员函数运算符重载

3.std:: string字符串类

字符串对象是一种特殊类型的容器,专门设计用于操作字符序列

cpp 复制代码
#include <iostream>
#include <string>
#include <string.h>
using namespace std;

int main()
{
    string s; // 调用无参构造
    // 判断是否为空
    cout <<  s.empty () << endl; // 1   bool:true:1  false:0

    string s1="hello";// 调用有参构造
    string s2("abc");// 调用有参构造
    cout << (s1==s2) << endl; // 0
    string s3(s2); //  调用拷贝有参构造 s3=s2

    // 保留几个字符
    // 参数1:char * 字符串
    // 参数2:整型数值
    string s4("ABCD",3);
    cout << s4 << endl; // ABC

    // 不保留前几个字符
    // 参数1:string 对象
    // 参数2:整型数值
    string s5(s1,3);
    cout << s5 << endl; // lo

    // 保存几个字符
    // 参数1:整型数值
    // 参数2:char字符
    string s6(5,'A');
    cout << s6 << endl; // AAAAA

    // 交换
    swap(s5,s6);
    cout << s5 << endl;// AAAAA
    cout << s6 << endl;// lo

    // 拼接
    string s7=s5+s6;
    cout << s7 << endl;// AAAAAlo

    // 最后追加字符串
    s7.append ("hhhhh");
    cout << s7 << endl;// AAAAAlohhhhh

    // 最后追加字符
    s7.push_back ('B');
    cout << s7 << endl;// AAAAAlohhhhhB

    // 插入
    // 参数1:插入位置
    // 参数2:插入的内容
    s7.insert (1,"22");
    cout << s7 << endl;// A22AAAAlohhhhhB

    // 删除
    // 参数1:从第几个元素开始删除
    // 参数2:删除的字符数量
    s7.erase (4,10);
    cout << s7 << endl;// A22AB

    // 替换
    // 参数1:起始位置(下标)
    // 参数2:替换的字符个数
    // 参数3:替换的内容
    s7.replace (1,2,"*");
    cout << s7 << endl;// A*AB

    // 清空
    s7.clear ();
    cout << "-----:" << s7 << endl;// -----:

    // string --->  char *
    char c[20];
    strcpy(c,s5.c_str ()); // 在尾部会添加\0
    cout << c << endl; // AAAAA


    char c1[20];
    // string --> char *
    // 参数1:保存的数组
    // 参数2:字符个数
    // 参数3:位置
    s5.copy(c1,6,0);
    cout << c1 << endl;// AAAAA

    return 0;
}
相关推荐
emfuture40 分钟前
龙芯2K300 PLC 在拉丝机收线系统改造中的应用:硬件选型、张力控制与国产化替代实践
java·开发语言·智能制造·plc·国产化替代
geovindu1 小时前
rust: Mediator Pattern
开发语言·后端·设计模式·rust·中介者模式·行为模式
传奇开心果编程1 小时前
【Rust入门练中学】第8课:错误处理
开发语言·rust·错误处理·编程语言理论·通用编程语言
郑同学的笔记1 小时前
【c++随笔30】C++ 注册回调函数
开发语言·c++
七夜zippoe2 小时前
启元 Q1 腿部运动学逆解:Python 算站立下蹲关节角
开发语言·python·ai·机器人·腿部运动学
熊猫钓鱼>_>2 小时前
精准碰一碰近场分享与拖拽投送实战:把文件“碰“进另一台设备【鸿蒙心迹】
开发语言·华为·harmonyos·鸿蒙·openharmony
lengxuenong2 小时前
树状数组 · 信息学学习手册2-离散化与逆序对
c++·学习·算法
十二2 小时前
【洛谷题解】P1115 最大子段和(前缀和 + 维护最小前缀)
数据结构·c++·算法·蓝桥杯
CodeGL2 小时前
9、Python基础之IO编程
开发语言·数据库·python