百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

C++:面向对象编程进阶(函数重载)

liebian365 2024-12-27 16:17 24 浏览 0 评论

在非面向对象的过程化语言中,要求每个过程或函数必须具有唯一的调用名,否则会导致编译错误。

面向对象程序设计语言提供使用同一函数名的机制,通过参数个数的不同或类型的不同来选择使用相应的代码,这就是函数重载。本节重点讲解成员函数重载和运算符重载。

成员函数重载

和普通函数类似,在一个类中也可以有成员函数重载。成员函数的重载在规则上和普通函数无差别,这里不再赘述。

例1 成员函数重载示例

#include <iostream>
  using namespace std;
class Sample
{
private:
  int i;
  double d;
  public:
  void setdata(int n) {i=n;d=0;}//setdata成员函数重载
  void setdata(int n,double x) {i=n,d=x;}//setdata成员函数重载
  void disp()
  {
  cout<<"i="<<i<<",d="<<d<<endl;
  }
};
void main()
{
Sample s;
  s.setdata(15);
  s.disp();
  s.setdata(20,23.8);
  s.disp();
}

运算符重载


C++有许多内置的数据类型,包括int,char, double等,每种类型都有许多运算符,如加、减、乘、除等。当用户定义了类的对象时,两个对象之间是不能进行这些操作的,比如Sample类的对象a+b,这样的语句如果没有重载+运算符就会出错。但C++允许用户把这些运算符添加到自己的类中以方便类对象之间的运算,就像内置类型的运算一样方便,比如对象a+b就很容易懂,当然也可以在类中定义一个对象间相加的函数,比如a.add (b)调用函数add()以实现两个对象a和b相加,但是这条语句不能像a+b那样更容易让人理解。

为了重载运算符,必须定义一个函数,并告诉编译器,遇到这个重载运算符就可以调用该函数,由这个函数来完成该运算符应该完成的操作。这种函数称为运算符重载函数,它通常是类的成员函数或者是友元函数。运算符的操作数通常也应该是类的对象。

运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。

(1)运算符重载为类的成员函数

运算符重载为类的成员函数的一般语法形式为:

函数类型 operator运算符(形参表)
{
	      函数体;
}

其中operator是定义运算符重载函数的关键字,它与其后的运算符一起构成函数名。

对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式oprd1 Boprd2,其中oprd1为类A的对象,则应当把B重载为类A的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。经过重载后,表达式oprdl B oprd2就相当于函数调用oprdl. operator B(oprd2)。

对于前置单目运算符U,如“-”(负号)等,如果要重载U为类的成员函数,用来实现表达式U oprd,其中oprd为类A的对象,则U应当重载为类A的成员函数,函数没有形参。经过重载之后,表达式U oprd相当于函数调用oprd. operator U()。

对于后置运算符“++”和“--”,如果要将它们重载为类的成员函数,用来实现表达式oprd++或oprd--,其中oprd为类A的对象,那么运算符就应当重载为类A的成员函数,这时函数要带有一个整型形参。重载之后,表达式oprd++和oprd--就相当于函数调用oprd.operator+ (0)和oprd. operator-- (0);

运算符重载就是赋予已有的运算符多重含义。通过重新定义运算符,使它能够用于特定类的对象执行特定的功能,这便增强了C++语言的扩充能力。

例2 双目运算符重载示例

#include <iostream>
  using namespace std;
class complex
{
public:
  complex() {real=imag=0;}
complex(double r,double i) {real=r;imag=i;}
complex operator+(const complex &c);//+运算符重载
friend void print(const complex &c);
private:
double real,imag;
};
inline complex complex::operator+(const complex &c)
{
return complex(real+c.real,imag+c.imag);
}
void print(const complex &c)
{
cout<<c.real<<"+"<<c.imag<<"i";
}
void main()
{
complex c1(2.0,3.0), c2(4.0,-2.0), c3;
  c3=c1+c2;
  cout<<"c1+c2=";
  print(c3);
}

例2中当执行c3=cl +c2时,相当于执行c3=cl. operator+(c2)语句,即当两个complex类对象做加法操作时相当于去调用运算符重载函数。该程序的最终结果为6+li。

例3 单目运算符重载示例

#include <iostream>
  using namespace std;
class Time
{
public:
  Time() {minute=0; sec=0;}
Time(int m, int s): minute(m),sec(s) { }
Time operator++();
void display() {cout<<minute<<":"<<sec<<endl;}
private:
int minute;
int sec;
};
Time Time::operator++()
{
if (++sec>=60)
{
sec-=60;
  ++minute;
}
  return *this;
}
int main()
{
Time time1(34,0);
  for (int i=0;i<60;i++)
  {
  ++time1;
    time1.display();
  }
  return 0;
}
 

例3中对++运算符进行重载。"++”运算符是单目运算符,只有一个操作数,因此,此运算符重载函数只有一个参数,且例6-3中该运算符重载函数作为类的成员函数时,则省略此参数。该例模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。

运算符重载为类的友元函数

与运算符重载为成员函数时不同的是,重载的友元函数不属于任何类,运算符的操作数都需要通过函数的形参表传递。操作数在形参表中从左到右出现的顺序就是用运算符写表达式时操作数的顺序。

这里分双目运算符和单目运算符两种情况,讨论运算符重载为友元函数的具体方式。如果有双目运算符U,它的其中一个操作数是类A的对象a,那么运算符U就可以重载为类A的友元函数,此友元函数的两个参数中,一个是类A的对象,另一个是其他对象,也可以是类A的对象。

这样双目运算符重载为类的友元函数后,假设运算符的一个操作数是对象b,则表达式aUb就相当于调用函数operator U(a, b)。如果有前置单目运算符U,比如前置“--”, a为类A的对象,如果要实现U a这样的运算,就可以把U重载为类A的友元函数,此友元函数只有一个形参,为类A的对象,重载后表达式U a相当于调用函数operator U(a)。如果是后置单目运算符U,如后置“++", a还是类A的对象,那么要实现a U这样的运算,也可以把U重载为类A的友元函数,此时友元函数就需要有两个形参,一个是类A的对象,另一个是整型形参,此整型形参没有实际意义,只是为了区分前置运算符和后置运算符的重载。重载后表达式aU就相当于调用函数operator U(a, 0)。

例4 修改例3为运算符重载为类的友元函数

#include <iostream>
  using namespace std;
class Time
{
public:
  Time() {minute=0; sec=0;}
Time(int m, int s): minute(m),sec(s) { }
Time operator++();
void display() {cout<<minute<<":"<<sec<<endl;}
private:
int minute;
int sec;
};
Time Time::operator++(Time &a)
{
if (++a.sec>=60)
{
a.sec-=60;
  ++a.minute;
}
  return a;
}
int main()
{
Time time1(34,0);
  for (int i=0;i<60;i++)
  {
  ++time1;
    time1.display();
  }
  return 0;
}

注意:该例中是单目运算符前置重载,而且重载为友元函数。因此operator++有一个参数,此参数为Time类对象。该程序结果和例3结果一样,均为显示由34:1到35:0一秒一秒的计数过程。

不管运算符重载是以上哪种形式,都需要遵循以下规则。

(1) C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。(不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::"、类型说明符"sizeof”、条件运算符“?:”。)

(2)重载之后运算符的优先级和结合性都不会改变。

相关推荐

go语言也可以做gui,go-fltk让你做出c++级别的桌面应用

大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...

旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗

这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...

codeblocks和VS2019下的fltk使用中文

在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...

FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库

FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...

中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux

IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...

Linux 5.13内核有望合并对苹果M1处理器支持的初步代码

预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...

Ubuntu系统下COM口测试教程(ubuntu port)

1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...

湖北嵌入式软件工程师培训怎么选,让自己脱颖而出

很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...

新阁上位机开发---10年工程师的Modbus总结

前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...

创建你的第一个可运行的嵌入式Linux系统-5

@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...

如何在Linux下给zigbee CC2530实现上位机

0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...

Python实现串口助手 - 03串口功能实现

 串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...

为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口

UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...

同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理

串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...

嵌入式linux为什么可以通过PC上的串口去执行命令?

1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...

取消回复欢迎 发表评论: