前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >运算符重载

运算符重载

作者头像
DeROy
发布2020-05-11 11:32:58
9090
发布2020-05-11 11:32:58
举报
文章被收录于专栏:编程学习基地编程学习基地

运算符重载

友元

友元函数

友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。 尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数

关键字friend
代码语言:javascript
复制
friend 返回值类型 函数名(参数列表);
friend void global_printf(const Point&that);    //友元函数
友元类

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)

代码语言:javascript
复制
//类前面加上friend声明友元类
class Point
{
    int m_x;
    int m_y;
public:
    friend class Point3D;//友元类
};
class Point3D
{
    Point m_p;
    int m_z;
public:
};

注意事项:

  1. 只有友元可以访问,其他依然不能访问。

若类B是类A的友元。则只有类B的成员函数可以访问类A中的隐藏信息

  1. 友元是单向的,不具有交换性。

若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

  1. 友元关系不具有传递性。

若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

友元类以及友元函数示例程序
代码语言:javascript
复制
//demo1.cpp
#include<iostream>
using namespace std;
class Point
{
    int m_x;
    int m_y;
public:
    Point(int x = 0, int y = 0);    //缺省构造函数    类内声明类外定义
    void Point_printf();            //类内数据打印函数
    friend void global_printf(const Point&that);    //友元函数 类外数据打印函数
    friend class Point3D;           //友元类
};
class Point3D
{
    Point m_p;
    int m_z;
public:
    Point3D(int x = 0, int y = 0, int z = 0);
    void Point3D_printf();
};
int main()
{
    Point point(10,20);
    cout << "========类函数打印========" << endl;
    point.Point_printf();
    cout << "========友元函数打印========" << endl;
    global_printf(point);
    cout << "========友元类打印========" << endl;
    Point3D point3d(10, 20, 30);
    point3d.Point3D_printf();
    cin.get();
    return 0;
}

Point::Point(int x, int y)
{
    m_x = x;
    m_y = y;
}

void Point::Point_printf()
{
    cout << this->m_x << " " << this->m_y << endl;
}

void global_printf(const Point&that)
{
    cout << that.m_x << " " << that.m_y << endl;
}

Point3D::Point3D(int x, int y, int z)
{
    m_p.m_x = x;
    m_p.m_y = y;
    m_z = z;
}

void Point3D::Point3D_printf()
{
    cout << m_p.m_x << " " << m_p.m_y << " " << m_z << endl;
}

打印结果:

代码语言:javascript
复制
========类函数打印========
10 20
========友元函数打印========
10 20
========友元类打印========
10 20 30

运算符重载

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

重载运算符可以使用成员函数非成员函数(一般是友元函数)两种方法

只能使用其中的一种方法

关键字operator
代码语言:javascript
复制
类名 operator运算符(const 类名& other);//成员函数实现
Complex operator+(const Complex& other);
可重载运算符

双目算术运算符

+ (加),-(减),*(乘),/(除),% (取模)

关系运算符

==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)

逻辑运算符

||(逻辑或),&&(逻辑与),!(逻辑非)

单目运算符

+ (正),-(负),*(指针),&(取地址)

自增自减运算符

++(自增),--(自减)

位运算符

| (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)

赋值运算符

=, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=

空间申请与释放

new, delete, new[ ] , delete[]

其他运算符

()(函数调用),->(成员访问),,(逗号),[](下标)

不可重载的运算符
  • .:成员访问运算符
  • .*, ->*:成员指针访问运算符
  • :::域运算符
  • sizeof:长度运算符
  • ?::条件运算符
  • #: 预处理符号
运算符重载注意事项
  1. 运算重载符不可以改变语法结构
  2. 运算重载符不可以改变操作数的个数
  3. 运算重载符不可以改变优先级
  4. 运算重载符不可以改变结合性
  5. 不能创建新的运算符
+,- 运算符重载
代码语言:javascript
复制
Complex operator+(const Complex& other);//+运算符重载    成员函数实现
代码语言:javascript
复制
friend Complex operator-(const Complex&A, const Complex&B);//-运算符重载    非成员函数实现
=赋值运算符重载

如果没有重载赋值运算符,操作系统会有缺省运算符重载,编译器提供的默认拷贝赋值操作符重载,同默认拷贝构造一样,默认拷贝赋值操作符重载同样是浅拷贝。

代码语言:javascript
复制
Complex operator=(const Complex&other);    //=运算符重载    成员函数实现
注意事项
  1. 避免自赋值
  2. 释放旧资源
  3. 分配新资源
  4. 拷贝新内容
  5. 返回自引用
代码语言:javascript
复制
//为了简便,只实现=运算符的避免自赋值,更多请看string类
Complex operator=(const Complex&other)
{
    if (&other != this)    //防止自赋值
    {
        m_real = other.m_real;
        m_imaginary = other.m_imaginary;
    }
    return *this;
}
前++,后++运算符重载
代码语言:javascript
复制
Complex operator++();        //前++运算符重载  成员函数实现
Complex operator++(int);    //后++运算符重载通过哑元实现    成员函数实现
流操作符>>,<<重载

cout是输出类的对象,而cin是输入类的对象,C++头文件iostream取自istream和ostream之意

流操作符>>,<<一般使用非成员函数实现,也就是友元函数实现,这样可以符合程序员的惯性思维

代码语言:javascript
复制
friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
friend istream &operator >> (istream &is, Complex&other);        //类的非成员函数重载>>提取运算符

让我们来看一下如果使用类成员方法重载流操作运算符会怎样一个结果

代码语言:javascript
复制
istream &operator>>(istream &is);        //类的成员函数重载>>提取运算符

这样定义的话使用的时候

代码语言:javascript
复制
Complex test;
test >> cin;    //类的成员函数提取运算符的调用

跟自己使用cin不太一样对不对,就像一个反人类的设计..

运算符重载示例程序1

代码语言:javascript
复制
//demo_2.cpp
#include<iostream>
using namespace std;
#define IS_MEMBER 0
class Complex
{
    double m_real;
    double m_imaginary;
public:
    Complex(double r = 0, double i = 0);
    void Complex_show();
    Complex operator+(const Complex& other);                    //+运算符重载    成员函数实现
    Complex operator=(const Complex&other);                     //=运算符重载    成员函数实现
    Complex operator++();       //前++运算符重载  成员函数实现
    Complex operator++(int);    //后++运算符重载  成员函数实现
    friend Complex operator-(const Complex&A, const Complex&B); //-运算符重载    非成员函数实现
    friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
#if IS_MENBER
    istream &operator>>(istream &is);       //类的成员函数重载>>提取运算符
#else
    friend istream &operator >> (istream &is, Complex&other);       //类的非成员函数重载>>提取运算符
#endif
};
int main()
{
    Complex complex_1(1, 8), complex_2(2, 5), temp;
    cout << "===========+操作符重载===========" << endl;
    temp = complex_1 + complex_2;
    temp.Complex_show();
    cout << "===========流操作符重载===========" << endl;
    Complex test;
#if IS_MENBER
    test >> cin;    //类的成员函数提取运算符的调用
#else
    cin >> test;
#endif
    complex_1 = test;
    cout << "===========-操作符重载===========" << endl;
    temp = complex_1 - complex_2;
    cout <<"temp:"<< temp << endl;
    cout << "============前++后++==========" << endl;
    Complex complex_3(1, 1);
    cout << complex_3++;
    cout << complex_3;
    cout << ++complex_3;
    return 0;
}

Complex::Complex(double r, double i)
{
    m_real = r;
    m_imaginary = i;
}

void Complex::Complex_show()
{
    cout << m_real << "+" << m_imaginary << "i" << endl;
}

Complex Complex::operator+(const Complex & other)
{
    Complex temp;
    temp.m_real = this->m_real + other.m_real;
    temp.m_imaginary = this->m_imaginary + other.m_imaginary;
    return temp;
}
Complex Complex::operator=(const Complex & other)
{
    if (&other != this)
    {
        m_real = other.m_real;
        m_imaginary = other.m_imaginary;
    }
    return *this;
}
Complex Complex::operator++()
{
    this->m_real = this->m_real + 1;
    return *this;
}
Complex Complex::operator++(int)
{
    Complex temp = *this;
    this->m_real = this->m_real + 1;

    return temp;
}
#if IS_MENBER
istream & Complex::operator >> (istream & is)
{
    cin >> this->m_real >> this->m_imaginary;
    // TODO: 在此处插入 return 语句
    return is;
}
#else
istream & operator >> (istream & is, Complex & other)
{
    is >> other.m_real >> other.m_imaginary;
    // TODO: 在此处插入 return 语句
    return is;
}

#endif

Complex operator-(const Complex & A, const Complex & B)
{
    Complex temp;
    temp.m_real = A.m_real - B.m_real;
    temp.m_imaginary = A.m_imaginary - B.m_imaginary;
    return temp;
}
ostream & operator<<(ostream & os, const Complex & other)
{
    os << other.m_real << "+" << other.m_imaginary << "i" << " ";
    // TODO: 在此处插入 return 语句
    return os;
}
代码语言:javascript
复制
//运行结果
===========+操作符重载===========
3+13i
===========流操作符重载===========
4 5
===========-操作符重载===========
temp:2+0i
============前++后++==========
1+1i 2+1i 3+1i
new,delete重载
代码语言:javascript
复制
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
void* operator new(size_t size);//类的非成员函数重载new
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
void  operator delete(void* ptr);//类的非成员函数重载delete

注意:对于new的重载返回值必须是void*;delete的重载返回值一定是void

运算符重载示例程序2

代码语言:javascript
复制
//demo_3.cpp
#include<iostream>
using namespace std;
class Integer
{
    char* m_str;
    int m_len;
public:
    Integer()
    {
        m_len = 1;
        m_str = new char[m_len];
        m_str[0] = '\0';
    }
    Integer(const char* str)
    {
        m_len = strlen(str) + 1;    //这个1留给\0
        m_str = new char[m_len];
        strcpy(m_str, str);
    }
    char & operator[](int i);
    //类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
    void* operator new(size_t size)
    {
        return (Integer*)malloc(size);
    }
    //类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
    void operator delete(void* ptr)
    {
        free(ptr);
    }
    friend ostream &operator<<(ostream &os, const Integer&other);
};

int main()
{
    Integer* arr = new Integer("hello world!");
    cout << *arr << endl;
    Integer str("hello C++!");
    for (int i = 0; i <= 10; i++)
    {
        cout << str[i];
    }
    delete arr;
    cin.get();
    return 0;
}
ostream & operator<<(ostream & os, const Integer & other)
{
    cout << other.m_str;
    // TODO: 在此处插入 return 语句
    return os;
}

char & Integer::operator[](int i)
{
    //TODO: 在此处插入 return 语句
    return m_str[i];
}
代码语言:javascript
复制
//运行结果
hello world!
hello C++!

End

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程学习基地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 友元
    • 友元函数
      • 关键字friend
    • 友元类
      • 友元类以及友元函数示例程序
      • 运算符重载
        • 关键字operator
          • 可重载运算符
            • 不可重载的运算符
              • 运算符重载注意事项
            • +,- 运算符重载
              • =赋值运算符重载
                • 注意事项
              • 前++,后++运算符重载
                • 流操作符>>,<<重载
                • 运算符重载示例程序1
                  • new,delete重载
                  • 运算符重载示例程序2
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档