C++-操作符重载、并实现复数类详解

首先回忆下以前学的函数重载

函数重载

  1. 函数重载的本质为相互独立的不同函数
  2. 通过函数名和函数参数来确定函数调用
  3. 无法直接通过函数名得到重载函数的入口地址
  4. 函数重载必然发生在同一个作用域中

类中的函数重载

  1. 静态成员函数能与普通成员函数建立重载关系
  2. 全局函数和成员函数不能构成重载关系

操作符重载(operator)

什么是操作符重载?

大家都知道,在C里,有'+,-,*,/'这些操作符,且它们的功能就是实现普通变量运算。

由于C++是面向对象的,遇到的变量大多都是对象,所以优化了C里的操作符,使它们拥有了重载能力.能通过一定方式,使对象能进行'+,-,*,/'等运算.

操作符的重载是以函数的方式进行.

操作符重载定义

操作符重载,通过operator关键字在函数前定义:

[返回类型] operator [需要重载的操作符](函数参数)

{

    //......

}

作符重载有几种方式 : 全局操作符重载函数、全局操作符重载函数

编译器首先会判断运算的若是对象,就会先从类里寻找成员操作符重载函数,若没找到,就会再去全局里寻找全局操作符重载函数.

注意事项:

  1. 操作符重载不能改变原操作符的优先级
  2. 操作符重载不能改变操作数的个数
  3. 操作符重载的参数一般设为const class_name &类型(若只设为const class_name,会产生临时对象)
  4. 在C++中,有些操作符必须需要有对象支持,所以只能为成员函数.这种被称为一元操作符

比如赋值(=)、下标([])、下标([])、调用(())和成员访问箭头(->):

Test t3=t2;  //相当于调用了: Test t3.operator =(t2); 里面会通过this指针来代替左侧数t3

有些操作符既可以当做成员操作符重载函数,也可以当做全局操作符重载函数,由于函数参数可以多个,便称为二元操作符
比如加法(+),与(&&),或(||),逗号(,)等:

以加法(+)为例,当设为全局操作符重载函数时,执行

Test t3=t1+t2; //相当于调用了: Test t3 = operator +(t1,t2);

以加法(+)为例,当设为成员操作符重载函数时,执行

Test t3=t1+t2; //相当于调用了: Test t3 =t1.operator +(t2); //里面会通过this指针来代替左侧数t1

多个重载的操作符重载函数

由于操作符重载函数带参数,所以可以存在多个相同的操作符重载函数

例如:

class Test
{

double x;

double y;

public:

Test operator +(const Test& t);        //实现Test t3=t1+t2

Test operator +(int i);            //实现Test t3=t1+1

Test operator +(double d);           //实现Test t3=t1+1.25

//... ...

};

初步试验

1.接下来,来个全局操作符重载函数例子:

#include "stdio.h"

class Test{

    int x;
    int y;

public:
    Test(int x=0,int y=0)
    {
       this->x=x;
       this->y=y;
    }
    int getx()
    {
       return x;
    }
    int gety()
    {
       return y;
    }

    friend Test operator + (const Test& t1,const Test& t2);
                         //声明友元函数,可以使用私有成员变量  

};

Test operator + (const Test& t1,const Test& t2)       //重载
{
    Test ret;
    ret.x=t1.x+t2.x;
    ret.y=t1.y+t2.y;
    return ret;
}

int main()
{
    Test t1(1,3);
    Test t2(2,4);
    Test t3= t1 + t2;      // 其实就是调用: Test t3 = operator +(t1,t2);

    printf("t3.x:%d t3.y:%d\n",t3.getx(),t3.gety()); 

    Test t4 =operator +(t1,t3);  // t4 =t1 +t3

    printf("t4.x:%d t4.y:%d\n",t4.getx(),t4.gety());

    return 0;
}

打印结果:

t3.x:3  t3.y:7
t4.x:4  t4.y:10

换成成员操作符重载函数例子:

#include "stdio.h"

class Test{

    int x;
    int y;

public:
    Test(int x=0,int y=0)
    {
     this->x =x;
     this->y =y;
    }

    int getx()
    {
       return x;
    }

    int gety()
    {
       return y;
    } 

  Test operator + (const Test& t2)
    {
       Test ret;

       ret.x = this->x + t2.x;
       ret.y = this->y + t2.y;
       return ret;
    }
};

int main()
{
    Test t1(1,3);
    Test t2(2,4);
    Test t3= t1 + t2;      // 其实就是调用: Test t3 =t1.operator +(t2);

    printf("t3.x:%d t3.y:%d\n",t3.getx(),t3.gety()); 

    Test t4 =t1.operator +(t3);  // t4 =t1 +t3

    printf("t4.x:%d t4.y:%d\n",t4.getx(),t4.gety());

    return 0;
    }

打印结果:

t3.x:3  t3.y:7
t4.x:4  t4.y:10

加深理解

由于C++里,没有复数的慨念,而在刚刚又学习了操作符重载,所以接下来便通过操作符重载来实现复数类

复数类应该具有

两个成员

实部a 、虚部b

运算操作符

+ - :  结果 = 两个实部进行加减,两个虚部进行加减

*   :  结果 = (a1+b1)(a2+b2)= (a1*a2 - b1*b2 )+( a2*b1 + a1*b2);

/   :  结果 =(a1+b1)/(a2+b2)= (a1*a2+b1*b2)/(a2* a2+b2* b2) +(b1*a2-a1*b2)/(a2* a2+b2* b2)

比较操作符:== ,!=

赋值操作符: =

求模成员函数 : 等于a^2+b^2的算术平方根

所以复数类的操作符重载共有以下几个:

1.写头文件Complex.h:

#ifndef __COMPLEX_H
#define __COMPLEX_H

class Complex{

private:
    double a;
    double b;

public:
    Complex(int a=0,int b=0);
    Complex operator + (const Complex& t);
    Complex operator - (const Complex& t);
    Complex operator * (const Complex& t);
    Complex operator / (const Complex& t);
    bool operator == (const Complex& t);
    bool operator != (const Complex& t);
    Complex& operator = (const Complex& t);

    double getModulus();

    double getA();
    double getB();
};

#endif
 

2.写源文件Complex.cpp

#include "Complex.h"
#include "math.h"

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

Complex Complex::operator + (const Complex& t)
{
    Complex ret; 

    ret.a = a + t.a;
    ret.b = b + t.b;
    return ret;
} 

Complex Complex::operator - (const Complex& t)
{
    Complex ret; 

    ret.a = a - t.a;
    ret.b = b - t.b;
    return ret;
}

Complex Complex::operator * (const Complex& t)
{
    Complex ret;
    ret.a = (a* t.a - b* t.b );
    ret.b = (t.a *b + a* t.b );
    return ret;
}

Complex Complex::operator / (const Complex& t)
{
    Complex ret;
    ret.a = (a* t.a + b* t.b)/(t.a * t.a + t.b * t.b);
    ret.b = (b* t.a - a* t.b)/(t.a * t.a + t.b * t.b);
    return ret;
}

bool Complex::operator == (const Complex& t)
{
    if((a== t.a)&&(b== t.b))
    return true;

    else
    return false;
}  

bool Complex::operator != (const Complex& t)
{
    if((a!= t.a)||(b!= t.b))
    return true;

    else
    return false;
}

Complex& Complex::operator = (const Complex& t)
{
    if(this != &t)
    {
     a = t.a;
     b = t.b;
    }
    return *this;
}  

double Complex::getModulus()
{
    return sqrt( a*a + b*b);
}

double Complex::getA()
{
    return a;
}  

double Complex::getB()
{
    return b;
}  

3.写测试文件test.cpp

#include "stdio.h"
#include "Complex.h"

int main()
{
    Complex t1(1,3);
    Complex t2(2,6);

    Complex t3=t1+t2;

    printf("t3.a=%f t3.b=%f\n",t3.getA(),t3.getB());

    printf("t3 Modulus:%f\n",t3.getModulus());

    Complex t4=t3;

    printf("t4==t3: %d\n",t4==t3);
    printf("t4!=t3: %d\n",t4!=t3);
    printf("t3==t1: %d\n",t3==t1);

    return 0;
}

4.编译运行

t3.a=3.000000  t3.b=9.000000
t3 Modulus:9.486833
t4==t3: 1                                   //为真
t4!=t3: 0                                   //为假
t3==t1: 0                                   //为假

以上所述是小编给大家介绍的C++-操作符重载、并实现复数类详解详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • c++运算符重载基础知识详解

    实际上,很多C++运算符已经被重载.eg:将*运算符用于地址,将得到存储在这个地址中的值,将他用于2个数字时,得到的将是他们的乘积.C++根据操作数的数目和类型来决定采用哪种操作. C++允许将运算符重载扩展到用户定义的类型.例如,允许使用+将两个对象相加.编译器将根据操作数的数目和类型决定使用加法定义.运算符重载可以使代码看起来更自然.例如,将2个数组相加是一种常见的运算.通常,需要使用下面这样的for循环来实现: 复制代码 代码如下: for (int i = 0; i < 20; i++)

  • 详解C++编程中的单目运算符重载与双目运算符重载

    C++单目运算符重载 单目运算符只有一个操作数,如!a,-b,&c,*p,还有最常用的++i和--i等.重载单目运算符的方法与重载双目运算符的方法是类似的.但由于单目运算符只有一个操作数,因此运算符重载函数只有一个参数,如果运算符重载函数作为成员函数,则还可省略此参数. 下面以自增运算符"++"为例,介绍单目运算符的重载. [例] 有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算.要求输出分和秒的值. #

  • C++运算符重载的方法详细解析

    运算符重载实质上是函数的重载 重载运算符的函数一般格式如下: 函数类型    operator  运算符名称    (形参表列) {对运算符的重载处理} 例如,想将"+"用于Complex(复数)的加法运算,函数的原型可以是这样的: 复制代码 代码如下: Complex operator + (Complex & c1,Complex &c2); 其中,operator是关键字,时候专门用于定义重载运算符的函数的,运算符名称就是C++提供给用户的预定运算符. 注意:函数

  • C++ 中重载和运算符重载加号实现矩阵相加实例代码

     C++ 重载+运算符重载加号 实现矩阵相加 学习C++ 基础知识,这里实现简单的实例,记录下自己学习生活,很简单,大家一起看看吧! 实例代码: #include<iostream> #include<iomanip> using namespace std; class Complex { private: int i,j,n,a[2][3]; public: Complex(); Complex operator+(Complex &c); void display()

  • 深入解析C++编程中的运算符重载

    C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作.例如: class complex { public: complex(double r=0.0,double I=0.0){real=r;imag=I;} void display(); private: double real; double imag; }; complex a(10,20),b(5,8); "a+b"运算如何实现?这时候我们需要自己编写程序来说明"

  • C++中的操作符重载详细解析

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

  • C++ 开发之实现操作符重载的实例

    C++操作符重载 实现效果图: 实例代码: Matrix.h #pragma once #include "vector" #include "iostream" #define rep(i,n) for(int i=1;i<=n;i++) //宏定义for循环,精简代码 using namespace std; class Matrix { public: //基本构造函数 Matrix(int Row=0, int Column=0); //拷贝构造函数或

  • C++-操作符重载、并实现复数类详解

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 静态成员函数能与普通成员函数建立重载关系 全局函数和成员函数不能构成重载关系 操作符重载(operator) 什么是操作符重载? 大家都知道,在C里,有'+,-,*,/'这些操作符,且它们的功能就是实现普通变量运算. 由于C++是面向对象的,遇到的变量大多都是对象,所以优化了C里的操作符,使它们拥

  • 下标操作符重载模拟多维数组详解

    最近在写游戏,就以地图类模版为例说明如何模拟多维数组吧! 复制代码 代码如下: template <typename T_CELL_STYLE>    class CMap    {    public:        CMap(IN UINT row_num, IN UINT col_num,                   IN T_CELL_STYLE cell_style = static_cast<T_CELL_STYLE>(0)); // 下标操作符重载      

  • python 接口_从协议到抽象基类详解

    抽象基类的常见用途:实现接口时作为超类使用.然后,说明抽象基类如何检查具体子类是否符合接口定义,以及如何使用注册机制声明一个类实现了某个接口,而不进行子类化操作.最后,说明如何让抽象基类自动"识别"任何符合接口的类--不进行子类化或注册. Python文化中的接口和协议 接口在动态类型语言中是怎么运作的呢?首先,基本的事实是,Python语言没有 interface 关键字,而且除了抽象基类,每个类都有接口:类实现或继承的公开属性(方法或数据属性),包括特殊方法,如__getitem_

  • C++ 中函数重载、覆盖与隐藏详解

    C++ 中函数重载.覆盖与隐藏详解 在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计:不管是面向对象编程,还是基于泛型编程,函数都可以随处而见.在谈论C++中的函数重载.覆盖和隐藏之前,先回顾下函数的基础知识. 函数的声明包括函数的返回值类型,函数名称,参数列表(参数的类型.参数的个数.参数的顺序).例如,声明一个两个整数之和的函数,int iAdd(int iNum1,int iNum2);而函数的定义可以理解为对函数功能的详尽而准确的解说,通俗点,就是实现函数"ho

  • AndroidStudio中重载方法@Override的使用详解

    在我们使用Android Studio时,创建一个类是继承于Android中已有的类时,我们会对原有类中的方法进行重载,Android Studio为我们提供了快捷的插入重载的方法,便于开发.减轻了工作量. 当我们继承一个Android中已有的类时,需要对其函数进行重载只需要点击菜单栏 Code->Override Methods,会跳出可以重载的函数,寻找需要的函数即可. 其中重载函数前都会有@Override标志. public MyService extends Service{ @Ove

  • Java基础之Object类详解

    object类的介绍 object是所有类的直接父类或者是间接父类,为什么这么说呢? 可以查询java8的API帮助文档: 可见在这样的一个类树中,所有的类的根还是Object类 在IDEA中新建一个类,系统会默认继承Object类 public class Pet extends Object{ } 那么Dog继承了Pet类的属性和行为方法,还会继承Object类的属性和行为方法了吗?这一点是肯定的,Pet类作为Object类的子类,Dog类作为Pet类的子类,所以说Object是Dog类的间

  • Java基础之重载(Overload)与重写(Override)详解

    一.重载(Overload) 重载是在一个类里面,方法名字相同,而参数不同.返回类型可以相同也可以不同. 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表. 最常用的地方就是构造器的重载. 重载的好处: 1.不用为了对不同的参数类型或参数个数,而写多个函数. 2.多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数. 3.重载的最直接作用是方便了程序员可以根据不同的参数个数,顺序,类型,自动匹配方法

  • Springboot自动配置与@Configuration配置类详解

    目录 @Configuration 注意点1 注意点2 注意点3 注意点4 springboot自动配置 @Configuration 注意点1 配置类(@Configuration下的这个类)其实相当于一个工厂, 标注 @Bean 注解的方法相当于工厂方法 考虑有如下例子: @Configuration // 注意点1: 配置类其实相当于一个工厂, 标注 @Bean 注解的方法相当于工厂方法 static class MyConfig { @Bean public Bean1 bean1()

  • java System类和Arrays类详解

    目录 前言 一.介绍 二.知识点介绍 三.知识点详解 1.概念 2.常用方法 3.注意事项 4.Arrays类 4.1.Arrays类的常用方法 4.2. 精炼练习 结语: 前言 这一篇我们聊一下System类和Arrays类,本来不想聊这个的,我感觉大家对这个一看就会,但是又想到我这个文章分类,我想表达的东西,不能缺席,所以这篇还是发来. 一.介绍 天天说用System.out.println()来输出,那么我有个小问题想请教,out是一个变量还是一个内部类呢?大型而系统的知识都有各种专题来详

  • 基于Java中的StringTokenizer类详解(推荐)

    StringTokenizer是字符串分隔解析类型,属于:Java.util包. 1.StringTokenizer的构造函数 StringTokenizer(String str):构造一个用来解析str的StringTokenizer对象.java默认的分隔符是"空格"."制表符('\t')"."换行符('\n')"."回车符('\r')". StringTokenizer(String str,String delim)

随机推荐