C++运算符重载总结(真的很详细了w(?Д?)w)

C++运算符重载总结(真的很详细了w(?Д?)w)

概述

运算符重载可以使得一些特殊类型参与运算,我是这样理解的。


使用友元形式的运算符重载

//一般形式
class x{
    friend 返回类型 operator 运算符(形参表);
};
返回类型 operator 运算符(形参表)
{}

双目运算符

所以加减乘除就可以这样来进行声明了

返回类型 operator +(-、*、/) (形参表);

单目运算符

- & ! ++(前),++(后)等。下面以++(后)来进行一个示例:

class code{
    int x, y;
};
code operator++(code& op, int)//第二个参数仅仅表示这个++是后缀加
{
    code tmp(op);
    x++;
    y++;
    return tmp;//返回增加之前的状态,这样也对后加加有了进一步理解了。
}

总结:

  1. 运算符重载可以返回任何类型,甚至是void类型,但是通常都是返回和操作数相同的类型。
  2. 下面运算符只能使用成员函数运算符重载,不能使用友元函数来重载。
    运算符名称
    = 等号
    [] 下标运算符
    () 函数调用运算符
    -> 指针成员运算符
  3. 对于同一个运算符,可以写多个函数来进行重载。

使用成员运算符进行重载

//一般形式
class x{
    返回类型 operator 运算符(参数表);
}
返回类型 x::operator 运算符(参数表)
{
    具体实现
}

双目运算符重载

这里需要注意的是:参数表中的个数会少一个,因为左操作数是隐含在this中的。
但是类内的静态函数没有this指针。

例如:

class code{
    int x, y;
    public:
        code(int a, int b):x(a), y(b){}
        code operator+(code p){
            return code(x+p.x, y+p.y);
        }
};
code A(1, 2), B(3, 4);
code C=A+B;//这时C.x=4, C.y=6;

单目运算符重载

形式和上面差不多,这里不再赘述。


运算符重载需要注意的几个问题

  1. c++语言只能对已经有的c++运算符进行重载,不允许用户自己定义新的运算符。
  2. 绝大多数运算符都能重载,但是有例外,下面五个不能进行重载
    名称
    . 成员访问运算符
    .* 成员指针访问运算符
    :: 作用域运算符
    sizeof 长度运算符
    ?: 条件运算符
  3. 重载的功能应当和原有的功能类似
  4. 重载不能改变运算符的操作对象
  5. 重载不能改变运算符原有的优先级
  6. 重载不能改变运算符原有的结合特性
  7. 重载参数应该至少有一个是类对象,不能都是c++预定义的类型(要不然就没有意义了)
  8. 双目运算符一般两种重载形式都可以,但是有的时候只能用友元形式来进行重载。例如:
    AB::operator+(int x){
        return AB(a+x, b+x);
    }
    ob1=ob2+100; //这里这样调用是可以的,编译器理解为ob1=ob2.operator(100);
    //但是下面的情况就会出现问题
    ob1=100+ob2; //等价于ob1=100.operator(ob2);但是100不是一个对象

    如果我们定义下面两个友元函数就会很好的解决这个问题

    friend AB operator+(AB ob, int x);
    friend AB operator+(int x, AB ob);
    //这样ob1=100+ob2; ob1=ob2+100;都没有问题
    //这里我们也可以整合,使用类型转换函数,将int类型转换为对象类型,对象类型转换为int类型,不过真没啥意思

几个常见的运算符重载

等号“ = ”运算符重载,只能使用成员函数进行重载

这里我们重载=主要是进行深拷贝操作(当然这里也可以自己写一个拷贝构造函数来进行)。

在重载等号运算符重载时要注意自己等于自己的情况

mystring& mystring::operator=(mystring &s)
{
       if(this==&s)return *this;//防止出现s=s的赋值;
       if(p!=NULL)
           delete []p;
       p=new char[strlen(s.p)+1];
       strcpy(p, s.p);
       return *this;
   }

下标运算符重载[]

只能使用成员函数进行重载,要注意这是个双目运算符x[y],x是左操作符,y是右操作符**

返回类型 类名::operator[] (参数表){
    函数体
}
//有时返回类型可以使用引用类型,只要不是返回的变量不是在函数内声明的临时变量就可以
class AB{
    int num[10];
    int len;
    int& operator[](int);
}
int& AB::operator[](int b)
{
    if(b<0 || b>=10)
        return -1;
    else return num[b]; //这里num[b]不是一个临时变量,而是存在于对象中。
}

函数调用运算符重载()

只能使用成员函数进行重载

注意这里()看被作双目运算符的,x(y), x是左操作数,y是右操作数

//给出坐标,返回二维矩阵的某个元素的值.
class matrix{
    int *m;//用一维的数组来进行模拟
    int row, col; //行数,列数
}
int& matrix::operator()(int r, int c){
    return *(m+r*col+c);
}
m(3, 5)//这里解释为m.operator()(3, 5);

()运算符是唯一一个可带多个右操作数的运算符函数


输出运算符和输入运算符的重载

<<运算符的重载

定义原型:需要注意成员函数形式和友元函数形式的区别,他们调用方式不相同

//成员函数类型,注意如果使用下面的类型,那么调用的方式是:对象名<<cout;
ostream& operator<<(ostream& out){
    out<<x<<" "<<y<<endl;
    return out;
}
ob<<cout;//相当于ob.operator<<(cout);
//因为上面这种形式有点反直觉,所以很少用,所以大部分都是采用友元形式

//友元函数类型
friend ostream& operator<<(ostream& out, 自定义类名& 对象名){
    //out可以改为别的名
    out<<对象.x<<对象.y<<endl;
    return out;
}
cout<<ob; //使用这种形式来进行输出

对于<<的参数详解,《C++ Primer中文版:第五版》\(494\)页是这样解释的:

输出运算符的第一个形参是一个非常量的ostream对象的引用。之所以ostream是非常量是因为向流写入内容会改变其状态;而该形参是因为我们无法复制一个ostream对象。

第二个形参一般来说是一个常量的引用,该常量是我们想要打印的类类型。第二个形参是引用的原因是我们希望避免赋值实参;而之所以该形参可以是常量是因为(通常情况下)打印对象不会改变对象的内容。

为了与其他输出运算符保持一致,operator<<一般要返回它的ostream形参。

>>输入运算符重载

这里的基本规则和上面重载输出运算符差不多,需要多注意的是,输入过程中要考虑到输入可能失败的情况。

原文地址:https://www.cnblogs.com/alking1001/p/12003178.html

时间: 2024-10-08 23:25:36

C++运算符重载总结(真的很详细了w(?Д?)w)的相关文章

【C++】运算符重载

这是C++的特色,也是C++比较难的一个基本语法,但是,如果你把运算符重载看成一个特殊的类方法,且这个类方法的名称就是运算符,一切就变得简单了. 下面用一个简单的程序说明这个问题: 声明两个3x3二维矩阵a,b,其实就是Matrix类,里面就用私有的长度为9的一维数组存储数据.只是打印的时候,打成二维数组的样子 实现~a或者~b就能直接打印a与b,也就是~相当于把a,b打印出来,此乃单目运算符重载. 实现a+b,返回另一个相加之后的矩阵c. 也就是说做到如下图的效果: 代码如下: #includ

C++ 运算符重载

C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作.比如对象a和对象b, 那么 a+b 就需要用户自己定义它怎么相加,这时就用到了运算符重载. 运算符重载规则如下: ①. C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符. ②. 重载之后运算符的优先级和结合性都不会改变. ③. 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造.一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对

C++运算符重载的妙用

运算符重载(Operator overloading)是C++重要特性之中的一个,本文通过列举标准库中的运算符重载实例,展示运算符重载在C++里的妙用.详细包含重载operator<<,operator>>支持cin,cout输入输出.重载operator[],实现下标运算.重载operator+=实现元素追加:重载operator()实现函数调用.假设你对C++的运算符重载掌握的游刃有余.那就无需继续往下看了. 运算符重载带来的优点就是--让代码变得简洁.以下将展示几个标准库因使

Python 3 之 运算符重载详解

基础知识 实际上,"运算符重载"只是意味着在类方法中拦截内置的操作--当类的实例出现在内置操作中,Python自动调用你的方法,并且你的方法的返回值变成了相应操作的结果.以下是对重载的关键概念的复习: 运算符重载让类拦截常规的Python运算. 类可重载所有Python表达式运算符 类可以重载打印.函数调用.属性点号运算等内置运算 重载使类实例的行为像内置类型. 重载是通过特殊名称的类方法来实现的. 换句话说,当类中提供了某个特殊名称的方法,在该类的实例出现在它们相关的表达式时,Pyt

【c++笔记十】运算符重载

2015年2月1日 阴雨 周日 今天难得休息,闲来无事就往岳麓山走了一遭,作为一个有情怀的程序猿就应该培养B格,不对,培养情操.拍了点雾凇,可以去我QQ空间看看. 今天笔记里要说的内容是:运算符重载.就像函数重载,运算符也可以重载.到底是什么样的重载呢?请听下回分解.哦不对,请看下面分解. --------------------------------------分割线------------------------------------------ 一.什么是运算符的重载? 我们先一起来看

【技术分享】很详细的JS底层分析

1. 序言现在学的东西很容易忘记,写这篇文章的目的是能让我在需要时快速找回当时的感觉. 入门学习和参考手册建议翻阅JavaScript.The.Definitive.Guide.5th.Edition的附录(有电子版). 2. 准备设置服务器*.xml的MIME为text/xml ,Windows Xp自带的IIS的设置如下图 js_0000.png Firefox上有许多插件是开发必备的,用法大家Google,我列一下名称 FireBug Web Developer Toolbar Greas

4.1.7 特殊方法与运算符重载

Python的类有大量的特殊方法,其中比较常见的是构造函数和析构函数.Python中类的构造函数是__init__(),一般用来为数据成员设置初始值或进行其他必要的初始化工作,在创建对象时被自动调用和执行.如果用户没有设计构造函数,Python将提供一个默认的构造函数用来进行必要的初始化工作.Python中类的析构函数是__del__(),一般用来释放对象占用的资源,在Python删除对象和回收对象空间时别自动调用和执行.如果用户没有编写析构函数,Python将提供一个默认的析构函数进行必要的清

运算符重载三种形式(成员函数,友元函数,普通函数)详解

首先,介绍三种重载方式: 1 //作为成员函数重载(常见) 2 class Person{ 3 Private: 4 string name; 5 int age; 6 public: 7 Person(const char* name, int age):name(name),age(age){} 8 bool operator<(const Person& b); 9 10 }; 11 bool Person::operator<(const Person& b) 12 {

C++_基础_运算符重载2

内容: (1)只能用成员形式重载的运算符 (2)new/delete操作符的重载 (3)封装和继承的初识 (4)继承的特性 (5)子类及其函数的特性 (6)多重继承和虚继承 1.只能用成员形式重载的运算符(1)[] 下标操作符 (2)() 函数操作符(3)* -> 间接操作符 2.new/delete操作符的重载 注意: 如果需要在调用构造函数之前做一些初始化工作/在调用析构函数之后做一些善后工作,则可以通过new/delete运算符重载的函数来实现 3.封装和继承的初识3.1 概念(1)封装