C++运算符重载学习总结

在C ++中,我们可以使运算符适用于用户定义的类。 这意味着C ++能够为运算符提供数据类型的特殊含义,这种能力称为运算符重载。

例如,我们可以在像String这样的类中重载运算符‘+‘,这样我们就可以通过使用+来连接两个字符串。

其它示例中算术运算符可以重载的的类是复数,小数,大整数等。

运算符重载的语法格式:

Return_Type classname :: operator op(Argument list)

{

Function Body

}

在上面的语法中,Return_Type是要返回给另一个对象的值类型,operator op是运算符是关键字的函数,op是要重载的运算符。

运算符函数必须是非静态(成员函数)或友元函数。

运算符重载可以通过三种方法完成,它们是

1)      重载一元运算符。

2)      重载二元运算符。

3)      使用友元函数重载二元运算符。

以下是定义运算符函数的一些条件/规则:

l  在非静态函数的情况下,二元运算符应该只有一个参数,而一元不应该有一个参数。

l  在友元函数的情况下,二元运算符应该只有两个参数,而一元应该只有一个参数。

l  如果实现了运算符重载,则所有类成员对象都应该是公共的。

运算符函数和普通函数有什么区别?

运算符函数与普通函数相同。 唯一的区别是,运算符函数的名称始终是operator关键字,后跟运算符符号,并且在使用相应的运算符时调用运算符函数。

除了极个别的运算符外,大部分运算符都可以被重载。

以下是可以重载的运算符列表:

以下是不可以重载的运算符列表:

为什么(点),::,?:和sizeof不可以重载看这里解释。

关于运算符重载的重要方面:

1)为了使操作符重载起作用,其中一个操作数必须是用户定义的类对象。

2)赋值运算符:编译器自动为每个类创建一个默认赋值运算符。 默认赋值运算符确实将右侧的所有成员分配到左侧,并且在大多数情况下都能正常工作(此行为与复制构造函数相同)。

3)转换运算符:我们还可以编写可用于将一种类型转换为另一种类型的转换运算符。重载的转换运算符必须是成员方法。 其他运算符可以是成员方法或全局方法。

4)任何可以用单个参数调用的构造函数都可以用作转换构造函数,这意味着它也可以用于隐式转换为正在构造的类。

综合例子:学习测试,仅供参考!

OperatorOverloadingClass.h


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 
#ifndef OPERATOROVERLOADINGCLASS_H
#define OPERATOROVERLOADINGCLASS_H

#include <iostream>
using namespace std;

const int SIZE = 10;

class OperatorOverloadingClass
{
public:
    OperatorOverloadingClass();
    OperatorOverloadingClass(const int &number,
                             const float &fnumber);

// 赋值运算符
    void operator = (const OperatorOverloadingClass &obj)
    {
        m_number = obj.m_number;
    }

// 函数调用()运算符
    OperatorOverloadingClass operator()(int a, int b, int c)
    {
        OperatorOverloadingClass D;
        // just put random calculation
        D.m_number = a + b + c;
        return D;
    }

void print();

/* OperatorOverloading
    */
    // 算术运算符
    // +
    OperatorOverloadingClass operator + (const OperatorOverloadingClass &obj);
    // -
    OperatorOverloadingClass operator - (const OperatorOverloadingClass &obj);
    // *
    OperatorOverloadingClass operator * (const OperatorOverloadingClass &obj);
    // /
    OperatorOverloadingClass operator / (const OperatorOverloadingClass &obj);
    // %
    OperatorOverloadingClass operator % (const OperatorOverloadingClass &obj);

// 关系运算符
    // <
    bool operator < (const OperatorOverloadingClass &obj);
    // >
    bool operator > (const OperatorOverloadingClass &obj);
    // <=
    bool operator <= (const OperatorOverloadingClass &obj);
    // >=
    bool operator >= (const OperatorOverloadingClass &obj);
    // ==
    bool operator == (const OperatorOverloadingClass &obj);
    // !=
    bool operator != (const OperatorOverloadingClass &obj);

// 位运算符
    // ^
    OperatorOverloadingClass operator ^ (const OperatorOverloadingClass &obj);
    // &
    OperatorOverloadingClass operator & (const OperatorOverloadingClass &obj);
    // |
    OperatorOverloadingClass operator | (const OperatorOverloadingClass &obj);

// 逻辑运算符
    // &&
    bool operator && (const OperatorOverloadingClass &obj);
    // ||
    bool operator || (const OperatorOverloadingClass &obj);

// 取地址运算符&
    int *operator &()
    {
        return &this->m_number;
    }
    // 内存操作运算符*
    int operator *(OperatorOverloadingClass *obj)
    {
        return obj->m_number;
    }

// 输入输出运算符
    // <<
    friend ostream &operator<<(ostream &output, const OperatorOverloadingClass &obj )
    {
        output << "number : " << obj.m_number;
        return output;
    }
    // >>
    friend istream &operator>>(istream &input, OperatorOverloadingClass &obj)
    {
        input >> obj.m_number;
        return input;
    }

// 自增自减运算符
    // ++i
    OperatorOverloadingClass operator ++();
    // i++
    OperatorOverloadingClass operator ++(int);
    // --i
    OperatorOverloadingClass operator --();
    // i--
    OperatorOverloadingClass operator --(int);

// 数组成员访问运算符[]
    int &operator[](int i)
    {
        if( i > SIZE )
        {
            cout << "Index out of bounds" << endl;
            // return first element.
            return arr[0];
        }
        return arr[i];
    }

// 类成员访问运算符->
    // https://www.cnblogs.com/codingmengmeng/p/9064702.html

// 复合赋值运算符:+=、-=、*=、/=、%=、<<=、>>=、^=、&=、|=
    void operator += (const OperatorOverloadingClass &obj)
    {
        m_number += obj.m_number;
    }
    // 其余类似

// 重载类型转换
    operator int()
    {
        return m_number;
    }
    operator float()
    {
        return m_fnumber;
    }

// new delete
    void *operator new(size_t size);
    void operator delete(void *p);
    void *operator new[](size_t size);
    void operator delete[](void *p, size_t size);

private:
    int     m_number;
    float   m_fnumber;
    int     arr[SIZE];
};

#endif // OPERATOROVERLOADINGCLASS_H

OperatorOverloadingClass.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
 
#include "OperatorOverloadingClass.h"
#include <QDebug>

OperatorOverloadingClass::OperatorOverloadingClass()
{
    m_number = 0;
    m_fnumber = 0.0;
    for(int i = 0; i < SIZE; i++)
    {
        arr[i] = i;
    }
}

OperatorOverloadingClass::OperatorOverloadingClass(const int &number,
        const float &fnumber)
    : m_number(number)
    , m_fnumber(fnumber)
{
    for(int i = 0; i < SIZE; i++)
    {
        arr[i] = i;
    }
}

void OperatorOverloadingClass::print()
{
    qDebug() << "m_number =" << m_number;
}

OperatorOverloadingClass OperatorOverloadingClass::operator +(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = this->m_number + obj.m_number;
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator -(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = this->m_number - obj.m_number;
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator *(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = this->m_number * obj.m_number;
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator /(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = this->m_number / obj.m_number;
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator %(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = this->m_number % obj.m_number;
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator ^(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = (this->m_number) ^ (obj.m_number);
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator &(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = (this->m_number) & (obj.m_number);
    return out;
}

OperatorOverloadingClass OperatorOverloadingClass::operator |(const OperatorOverloadingClass &obj)
{
    OperatorOverloadingClass out;
    out.m_number = (this->m_number) | (obj.m_number);
    return out;
}

bool OperatorOverloadingClass::operator &&(const OperatorOverloadingClass &obj)
{
    return (this->m_number) && (obj.m_number);
}

bool OperatorOverloadingClass::operator ||(const OperatorOverloadingClass &obj)
{
    return (this->m_number) || (obj.m_number);
}

bool OperatorOverloadingClass::operator <(const OperatorOverloadingClass &obj)
{
    if(m_number < obj.m_number)
    {
        return true;
    }
    return false;
}

bool OperatorOverloadingClass::operator >(const OperatorOverloadingClass &obj)
{
    if(m_number > obj.m_number)
    {
        return true;
    }
    return false;
}

bool OperatorOverloadingClass::operator <=(const OperatorOverloadingClass &obj)
{
    if(m_number <= obj.m_number)
    {
        return true;
    }
    return false;
}

bool OperatorOverloadingClass::operator >=(const OperatorOverloadingClass &obj)
{
    if(m_number >= obj.m_number)
    {
        return true;
    }
    return false;
}

bool OperatorOverloadingClass::operator ==(const OperatorOverloadingClass &obj)
{
    if(m_number == obj.m_number)
    {
        return true;
    }
    return false;
}

bool OperatorOverloadingClass::operator !=(const OperatorOverloadingClass &obj)
{
    if(m_number != obj.m_number)
    {
        return true;
    }
    return false;
}

// overloaded prefix ++ operator
OperatorOverloadingClass OperatorOverloadingClass:: operator++ ()
{
    ++m_number;          // increment this object
    return OperatorOverloadingClass(m_number, 0.0);
}

// overloaded postfix ++ operator
OperatorOverloadingClass OperatorOverloadingClass:: operator++( int )
{

// save the orignal value
    OperatorOverloadingClass T(m_number, 0.0);

// increment this object
    ++m_number;

// return old original value
    return T;
}

// overloaded prefix -- operator
OperatorOverloadingClass OperatorOverloadingClass:: operator-- ()
{
    --m_number;          // increment this object
    return OperatorOverloadingClass(m_number, 0.0);
}

// overloaded postfix -- operator
OperatorOverloadingClass OperatorOverloadingClass:: operator--( int )
{

// save the orignal value
    OperatorOverloadingClass T(m_number, 0.0);

// increment this object
    --m_number;

// return old original value
    return T;
}

void *OperatorOverloadingClass::operator new(size_t size)
{
    return malloc(size);
}

void OperatorOverloadingClass::operator delete(void *p)
{
    free(p);
}

inline void *OperatorOverloadingClass::operator new[](size_t size)
{
    OperatorOverloadingClass *p = (OperatorOverloadingClass *)malloc(size);
    return p;
}

inline void OperatorOverloadingClass::operator delete[](void *p, size_t size)
{
    free(p);
}

原文地址:https://www.cnblogs.com/MakeView660/p/11102349.html

时间: 2024-11-15 00:55:51

C++运算符重载学习总结的相关文章

初探C++运算符重载学习笔记&lt;1&gt;

运算符重载 含义: 对抽象数据类型也能够直接使用C++提供的运算符 对已有的运算符赋予多重的含义 使同一运算符针对不同的数据类型产生不同的行为 目的: -->扩展C++运算符的适用范围,以用于类所表示的抽象数据类型 -->程序更简洁 -->代码可读性更好 例如complex_a和complex_b是两个复数对象,如果求和,希望能直接写成 complex_a + complex_b  这样的形式. 实质: 函数重载 返回值类型 operator 运算符(参数表) { .... } 在函数编

初步C++运算符重载学习笔记&amp;lt;3&amp;gt; 增量递减运算符重载

初步C++运算符重载学习笔记<1> 初探C++运算符重载学习笔记<2> 重载为友元函数     增量.减量运算符++(--)分别有两种形式:前自增++i(自减--i).后自增i++(自减i--) 因此当我们重载该运算符时,要重载对应形式的运算符. T & operator ++() // 前自增++i T & operator ++(int) //后自增 i++ 举例: #include <iostream> using namespace std; c

初探C++运算符重载学习笔记&amp;lt;2&amp;gt; 重载为友元函数

初探C++运算符重载学习笔记 在上面那篇博客中,写了将运算符重载为普通函数或类的成员函数这两种情况. 以下的两种情况发生.则我们须要将运算符重载为类的友元函数 <1>成员函数不能满足要求 <2>普通函数又不能訪问类的私有成员时 举例说明: class Complex{ double real, imag; public: Complex(double r, double i):real(r), imag(i){ }; Complex operator+(double r); };

初探C++运算符重载学习笔记&lt;3&gt; 增量减量运算符重载

初探C++运算符重载学习笔记<1> 初探C++运算符重载学习笔记<2> 重载为友元函数     增量.减量运算符++(--)分别有两种形式:前自增++i(自减--i),后自增i++(自减i--) 因此当我们重载该运算符时,要重载相应形式的运算符. T & operator ++() // 前自增++i T & operator ++(int) //后自增 i++ 举例: #include <iostream> using namespace std; c

运算符重载 学习总结

一元运算符重载 参考https://www.imooc.com/video/9588 - 号 友元函数重载 略 成员函数重载 class A{ public: A& operator-(); private: int m_a; int m_b; } A& A::operator-();{ m_a = -m_a; m_b = -m_a; return *this; } ++号(前置与后置) 略 二元运算符重载 参考https://www.imooc.com/video/9591 +号 成员函

C++运算符重载为友元函数学习笔记

初探C++运算符重载学习笔记 在上面那篇博客中,写了将运算符重载为普通函数或类的成员函数这两种情况. 下面的两种情况发生,则我们需要将运算符重载为类的友元函数 <1>成员函数不能满足要求 <2>普通函数又不能访问类的私有成员时 举例说明: class Complex{ double real, imag; public: Complex(double r, double i):real(r), imag(i){ }; Complex operator+(double r); };

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载、!运算符重载、赋值运算符重载 、String类([]、 +、 += 运算符重载)、&gt;&gt;和&lt;&lt;运算符重载

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载.!运算符重载.赋值运算符重载 .String类([]. +. += 运算符重载).>>和<<运算符重载 一.++/--运算符重载 1.前置++运算符重载 成员函数的方式重载,原型为: 函数类型 & operator++(); 友元函数的方式重载,原型为: friend 函数类型 & operator++(类类型 &); 2.后置++运算符重载 成员函数的方式重载,原型为:

C++ Primer 学习笔记_28_操作符重载与转换(3)--成员函数的重载、覆盖与隐藏、类型转换运算符、*运算符重载、-&gt;运算符重载

C++ Primer 学习笔记_28_操作符重载与转换(3)--成员函数的重载.覆盖与隐藏.类型转换运算符.*运算符重载.->运算符重载 一.成员函数的重载.覆盖与隐藏 对于类层次的同名成员函数来说,有三种关系:重载.覆盖和隐藏,理清3种关系,有助于写出高质量的代码. 1.成员函数的重载 重载的概念相对简单,只有在同一类定义中的同名成员函数才存在重载关系,主要特点时函数的参数类型和数目有所不同:但不能出现函数参数的个数和类型均相同,仅仅依靠返回值类型不同来区分的函数,这和普通函数的重载是完全一致

C++ Primer Plus学习笔记之运算符重载

C++ Primer Plus学习笔记之运算符重载 1,成员函数和友元函数选择的建议 下面我们先看两个例子: 成员函数重载 #include<iostream> using namespace std; class Complex { public: Complex(double r=0,double i=0) { re=r; im=i; } Complex operator+(const Complex& obj); Complex operator!(); void Display