类和对象(17)—— 操作符重载

1、操作符重载的基本语法

  所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。

  运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。例如,大家都已习惯于用加法运算符”+”对整数、单精度数和双精度数进行加法运算,如5+8,5.8+3.67等,其实计算机对整数、单精度数和双精度数的加法操作过程是很不相同的,但由于C++已经对运算符”+”进行了重载,所以就能适用于int,float,doUble类型的运算。

  又如”<<“是C++的位运算中的位移运算符(左移),但在输出操作中又是与流对象cout配合使用的流插入运算符,”>>“也是位移运算符(右移),但在输入操作中又是与流对象cin配合使用的流提取运算符。这就是运算符重载(operator overloading)。C++系统对”<<“和”>>“进行了重载,用户在不同的场合下使用它们时,作用是不同的。对”<<“和”>>“的重载处理是放在头文件stream中的。因此,如果要在程序中用”<<“和”>>”作流插入运算符和流提取运算符,必须在本文件模块中包含头文件stream(当然还应当包括”using namespace std“)。现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。

  运算符重载的本质是函数重载。

  重载函数的一般格式如下:

函数类型 operator操作符名称 (形参列表)
{
    重载实体;
}

  operator 运算符名称 在一起构成了新的函数名。比如

const Complex operator+(const Complex &c1, const Complex &c2);

  我们会说,operator+ 重载了重载了运算符+。

2、操作符重载的规则

(1)C++不允许用户自己定义新的运算符,只能对已有的 C++运算符进行重载。

  例如,有人觉得 BASIC 中用“* *”作为幂运算符很方便,也想在 C++中将“**”定义为幂运算符,用“3* *5”表示 35,这是不行。

(2)C++允许重载的运算符

  C++中绝大部分运算符都是可以被重载的。

  不能重载的运算符只有 4 个:

  前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符合sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。

(3)重载不能改变运算符运算对象(即操作数)的个数。

  如,关系运算符“>”和“<”等是双目运算符,重载后仍为双目运算符,需要两个参数。运算符”+“,”-“,”*“,”&“等既可以作为单目运算符,也可以作为双目运算符,可以分别将它们重载为单目运算符或双目运算符。
(4)重载不能改变运算符的优先级别。

  例如”*“和”/“优先级高于”+“和”-“,不论怎样进行重载,各运算符之间的优先级不会改变。有时在程序中希望改变某运算符的优先级,也只能使用加括号的方法 强制改变重载运算符的运算顺序。

(5)重载不能改变运算符的结合性。

  如,复制运算符”=“是右结合性(自右至左),重载后仍为右结合性。

(6)重载运算符的函数不能有默认的参数

  否则就改变了运算符参数的个数,与前面第(3)点矛盾。

(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一 个是类对象(或类对象的引用)。

  也就是说,参数不能全部是 C++的标准类型,以防止用户修改用于标准类型数据成 员的运算符的性质,如下面这样是不对的:

  复制代码 代码如下:

int operator + (int a,int b)

{
  return(a-b);

}

  原来运算符+的作用是对两个数相加,现在企图通过重载使它的作用改为两个数相 减。如果允许这样重载的话,如果有表达式 4+3,它的结果是 7 还是 1 呢?显然,这是 绝对要禁止的。

(8)用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算符”&“不 必用户重载。

复制运算符”=“可以用于每一个类对象,可以用它在同类对象之间相互赋值。因 为系统已为每一个新声明的类重载了一个赋值运算符,它的作用是逐个复制类中的数据 成员地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。

  例如,我们会去重载”+“以实现对象的相加,而不会去重载”+“以实现对象相减的功能,因为这样不符合我们对”+“原来的认知。

(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类 的成员函数也不是友元函数的普通函数。

案例一:复数相加

普通方法实现复数相加

  利用全局函数实现:

#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a,int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << ")" << endl;
    }

    friend Complex complexAdd(Complex &c1, Complex&c2);
private:
    int a;//实部
    int b;//虚部
};

Complex complexAdd(Complex &c1, Complex&c2)
{
    Complex temp(c1.a + c2.a, c1.b + c2.b);
    return temp;
}

int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);

    c1.printComplex();
    c2.printComplex();

    Complex c3 = complexAdd(c1, c2);
    c3.printComplex();

    return 0;
}

  利用成员函数实现:

#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a,int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << ")" << endl;
    }
    Complex complexAdd(Complex&another)
    {
        Complex temp(this->a + another.a, this->b + another.b);
        return temp;
    }

private:
    int a;//实部
    int b;//虚部
};

int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);

    c1.printComplex();
    c2.printComplex();

    Complex c3=c1.complexAdd(c2);
    c3.printComplex();

    return 0;
}

操作符重载方法实现复数相加:

  利用全局函数实现:

#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a,int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << "i)" << endl;
    }

    friend Complex operator+(Complex &c1, Complex &c2);

private:
    int a;//实部
    int b;//虚部
};

Complex operator+(Complex &c1, Complex &c2)
{
    Complex temp(c1.a + c2.a, c1.b + c2.b);
    return temp;
}

int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);

    c1.printComplex();
    c2.printComplex();

    Complex c3 = c1 + c2;//等同于Complex c3=operator+(c1, c2);
    c3.printComplex();

    return 0;
}

  利用成员函数实现:

#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a,int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << "i)" << endl;
    }

    Complex operator+(Complex &another)
    {
        Complex temp(this->a + another.a, this->b + another.b);
        return temp;
    }

private:
    int a;//实部
    int b;//虚部
};

int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);

    c1.printComplex();
    c2.printComplex();

    Complex c3 = c1 + c2;//等同于Complex c3=c1.operator+(c2);
    c3.printComplex();

    return 0;
}
#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a, int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << "i)" << endl;
    }

    friend Complex & operator+=(Complex &c1,Complex &c2);

private:
    int a;//实部
    int b;//虚部
};

Complex & operator+=(Complex &c1,Complex &c2)
{
    c1.a += c2.a;
    c1.b += c2.b;

    return c1;
}

int main(void)
{
    Complex c1(1, 2);
    Complex c2(3, 4);

    c1.printComplex();//(1, 2i)
    c2.printComplex();//(3, 4i)

    (c1 += c2) += c2;
    c1.printComplex();//(7, 10i)
    c2.printComplex();//(3, 4i)

    return 0;
}
#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(int a, int b)
    {
        this->a = a;
        this->b = b;
    }

    void printComplex()
    {
        cout << "(" << this->a << "," << this->b << "i)" << endl;
    }

    Complex& operator+=(Complex &another)
    {
        this->a += another.a;
        this->b += another.b;

        return *this;
    }

private:
    int a;//实部
    int b;//虚部
};

int main(void)
{
    Complex c1(1, 2);
    Complex c2(3, 4);

    c1.printComplex();//(1, 2i)
    c2.printComplex();//(3, 4i)

    (c1 += c2) += c2;
    c1.printComplex();//(7, 10i)
    c2.printComplex();//(3, 4i)

    return 0;
}

原文地址:https://www.cnblogs.com/yuehouse/p/9818754.html

时间: 2024-07-29 03:47:43

类和对象(17)—— 操作符重载的相关文章

C#面向对象课程 类与对象,方法重载,类的静态成员,命名空间和类库12月22日

一.类是面向对象课程的基本单元. 在类的里面可以直接定义字段(成员变量),也可以定义方法(函数). 例如: 这里的public是修饰符,修饰符的作用是用来限定它的可访问范围. 两个同范围(同一个类中,或者父子类中)两个同名但参数类型不同或者参数个数不同的方法互相间构成重载关系. 两个构成重载关系的方法(函数)必须满足以下条件: (1)方法(函数)名相同: (2)参数类型不同,或参数个数不同.这里需要注意的是,函数返回值类型的不同不是函数重载的判断条件. 二.静态成员 属性.方法和字段等成员是对象

C++ 模板类友元之输出流操作符重载

几个关键点: 需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行! 友元函数的函数名后面的<>,必须要有. #include <stdio.h> #include <iostream> using namespace std; //前置声明,你妹啊 template<class T> class A; template<class T> ostream &operator<< (ostream &out,

C++解析(17):操作符重载

0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Complex { int a; int b; public: Complex(int a = 0, int b = 0) { this->a = a; this->b = b; } int getA() { return a; } int getB() { return b; } friend Compl

c++ --&gt; 操作符重载

一.什么是操作符重载 操作符重载可以分为两部分:“操作符”和“重载”.说到重载想必都不陌生了吧,这是一种编译时多态,重载实际上可以分为函数重载和操作符重载.运算符重载和函数重载的不同之处在于操作符重载重载的一定是操作符.我们不妨先直观的看一下所谓的操作符重载: #include <iostream> using namespace std; int main() { int a = 2 , b = 3; float c = 2.1f , d = 1.2f; cout<<"

C#中如何利用操作符重载和转换操作符

原文:C#中如何利用操作符重载和转换操作符 操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成把两个整数加到一起的代码. 当编译器发现两个string类型的实例使用+操作符的时候,编译器会生成把两个字符串连接到一起的代码.那么编译器怎么就会知道这样做呢?如何进行操作符重载呢? 下面C#代码展示了一个类中如何进行操作符重载: namespace Do

5.7 C++函数调用操作符重载

参考:http://www.weixueyuan.net/view/6385.html 总结: 需要以类成员函数的形式对函数调用操作符"()"进行重载. 只有常成员函数才能处理常对象,故我们依然在类中提供两个版本的函数调用操作符重载函数.若调用对象为常对象(const),则必须用常函数. 这里面的关于在函数中抛出异常,在调用处捕捉异常,值得参考学习. 与下标操作符重载函数相同,我们同样需要以类成员函数的形式对函数调用操作符"()"进行重载.其声明语法只有一种形式: 

实现操作符重载的两种方式

操作符重载的实现方式有两种,即通过"友元函数"或者"类成员函数". 1.友元函数重载操作符的格式: 1 class 类名 2 { 3 friend 返回类型 operator 操作符(形参表); 4 }; 5 //类外定义格式: 6 返回类型 operator操作符(参数表) 7 { 8 //函数体 9 } 2.类成员函数实现操作符重载的格式: 1 class 类名 2 { 3 public: 4 返回类型 operator 操作符(形参表): 5 }; 6 //类

第十一章 类和对象

一.本章技能目标 掌握类和对象 理解封装 会创建和使用对象 二.内容 1 对象 分类是人们认识世界的一个很自然的过程,在日常生活中会不自觉地进行分类 什么是对象,对角是用来描述客户事物的一个实体 Java是一种面向对象的编程语言 1.1 身边的对象 用向对象方法来解决问题是,首先要对现实世界中的对象进行分析与归纳,找出哪些对象与要解决的问题是相关的 对象都有一些特征,这些特征是有别于其他对象 所以对象由特征和操作组成 1.2 对象的属性和方法 在面向对象的编程思想中,把对象的静态特征和动态特征分

Kotlin操作符重载:把标准操作加入到任何类中(KAD 17)

作者:Antonio Leiva 时间:Mar 21, 2017 原文链接:https://antonioleiva.com/operator-overload-kotlin/ 就像其他每种语言一样,在Kotlin中,已经预定义了一些操作符执行一定的操作. 最典型的是加(+),减(-),乘(*),除(/),而且还有很多. 类似Java这样的一些语言,这些操作符被限制在一些特定的数量类型上,且没有方法让其他类型数据使用这些操作符. 还有在像Scala这样的其他语言中,由于函数名称可接受任何符号,我