c++编程学习:多态性&重载

本文详细介绍了C++中的多态性和重载,包括函数重载和运算符重载。通过成员函数和友元函数实现复数对象的加法运算,并探讨了重载的规则和限制,以及不同类型的运算符重载实现方式,如双目和单目运算符的成员函数和友元函数重载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多态性与重载

  • 多态性是面向对象程序设计的重要特性之一。多态是会一个名字有很多种语义,或一个相同界面有很多多种实现;或是指发出同样的消息被不同类型的对象接收而导致完全不同的行为,即对象根据所接收到的消息做出相应的操作。

  • 消息主要是指对象成员函数的调用,不同的行为指不同的实现。

多态的实现:
  1. 函数重载
  2. 运算符重载
  3. 虚函数
函数重载
  • 多态性的一种形式,它是指允许在相同的作用域内,相同的函数名对应着不同得实现。
  • 函数重载的条件是要求函数参数的类型或个数有所不同。

在这里插入图片描述


  • 成员函数重载有三种方式:
  1. 在一个类中重载:参数的特征区分;例如:
    show(int, char); show(char*, float);

  2. 在不同类中重载:实用类作用域符::加以区分(不同类中重载,静态成员函数),例如:
    Circle::show(); Point::show();

  3. 根据类对象加以区分(不同类中重载,不同成员函数),例如:
    acircle.show() 调用 Circle::show()
    apoint.show() 调用 Point::show()

  4. 基类的成员函数在派生类中重载:继承时再介绍。

通过成员函数实现2个复数对象的加法运算
#include <iostream>
using namespace std;
class complex//复数类声明
{
public:	
	complex(double r=0.0,double i=0.0) //构造函数
    {	real=r;	imag=i;}void Show( );	//显示复数的值
       complex add(complex &c);//复数与复数相加的函数
private:	
	double real;
	double imag;
};	
complex  complex::add(complex &c2) //通过成员函数实现
{
	complex t;
	t.real=real+c2.real;
	t.imag=imag+c2.imag;
	return t;
}
void complex::Show()
{
	cout<<"("<<real<<","<<imag<<")"<<endl; 
}	

int main()     //主函数
{
	complex z1(1.5,2.8),z2(-2.3,3.4),z3;  //声明复数类的对象
	z3=z1.add(z2);//成员函数调用
	cout<<"z3=";
	z3.Show();
	return 0;
}
通过友元函数实现2个复数对象的加减运算
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
	complex(double r=0.0,double i=0.0)
        {real=r;imag=i;}//构造函数
	friend complex add(complex &c1,complex &c2); //add2个复数友元函数	
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
complex  add(complex &c1,complex &c2) //通过友元函数实现
{	complex t;
	t.real=c1.real+c2.real;
	t.imag=c1.imag+c2.imag;
	return t;
}
void complex::Show()
{	cout<<"("<<real<<","<<imag<<")"<<endl; 
}

int main()     //主函数
{
complex z1(1.5,2.8),z2(-2.3,3.4),z3;  //声明复数类的对象
z3=add(z1,z2);//友元函数调用
cout<<"z3=";
z3.Show();
return 0;
}
通过成员函数重载实现2个复数对象的加减运算,以及1个复数对象和1个实数对象加法运算
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
	complex(double r=0.0,double i=0.0){real=r;imag=i;}//构造函数
	complex add(complex &c2); //2个复数对象加的成员函数
	complex add(double e); //1个复数对象与1个实数加的成员函数	
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
void complex::Show()
{	cout<<"("<<real<<","<<imag<<")"<<endl; 
}
complex  complex::add(complex &c2) //通过成员函数实现
{	complex t;
	t.real=real+c2.real;
	t.imag=imag+c2.imag;
	return t;
}
complex  complex::add(double e) //通过成员函数实现
{	complex t;
	t.real=real+e;
	t.imag=imag;
	return t;
}
int main()     //主函数
{complex z1(1.5,2.8),z2(-2.3,3.4),z3,z4; 
z3=z1.add(z2);//成员函数调用
z4=z3.add(5.6);
cout<<"z3=";
z3.Show();
cout<<"z4=";
z4.Show();
return 0;
}
通过友元函数重载实现2个复数对象的加法运算,以及一个复数和一个实数的加法运算。
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
complex(double r=0.0,double i=0.0)//构造函数
{real=r;imag=i;}
friend complex add(complex &c1,complex &c2); //2个复数对象加友元函数
friend complex add(complex &c1,double e); //1个复数对象与1个实数加友元函数
void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};
void complex::Show()
{	cout<<"("<<real<<","<<imag<<")"<<endl; 
}
complex  add(complex &c1,complex &c2) //通过友元函数实现
{	complex t;
	t.real=c1.real+c2.real;
	t.imag=c1.imag+c2.imag;
	return t;
}
complex add(complex &c1,double e) //通过友元函数实现
{complex t;
t.real=c1.real+e;
t.imag=c1.imag;
return t;
}
int main()     //主函数
{complex z1(1.5,2.8),z2(-2.3,3.4),z3,z4; z3=add(z1,z2);
z4=add(z3,5.6);
cout<<"z3=";
z3.Show();
cout<<"z4=";
z4.Show();
return 0;
}
小结
  • 定义一种新的数据类型,就同时需要定义对这种类型数据的操作,最基本的方法就是定义一系列能够完成各种运算的函数。
  1. 利用成员函数实现运算,函数中可方便的访问复数对象中的私有函数。
  2. 利用友元函数实现运算,提供了一种非成员函数访问复数对象中的私有成员的手段。
  3. 利用函数重载这一种多态性形式,提供在相同的作用域内,相同的函数名对应着不同的实现。
运算符重载

运算符重载是对已有的运算符富余多重含义。有两种方式:

  1. 重载为成员函数
  2. 重载为友元函数
实质
  • 必要性
    • c++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)。
  • 实现机制
    • 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。
    • 编译系统对运算符的选择,遵循函数重载的选择原则。
规则和限制
  1. 可以重载c++中除下列运算符外的所有运算符:
    . * :: ?: sizeof
  2. 只能重载c++语言中已有的运算符,不可臆造新的。
  3. 不改变原运算符的优先级和结核性。
  4. 不能改变操作数个数。
  5. 经重载的运算符,其操作数中至少应该有一个是自定义类型(类)。
声明形式
函数类型   operator 运算符 (形参)
{
	body;
}
//作为成员函数重载时,第一个操作数就是当前对象本身,因此她并不需要出现在参数表中。
  1. 重载为类成员函数时:
    参数个数 = 原操作数个数 - 1(后置++ 、 --除外)
  2. 重载为友元函数时:
    参数个 = 原操作数个数,且至少应该有一个自定义类型的形参。
    由于友元函数不是任何类的成员函数,因此重载是必须在参数表中显示的给出所有的操作数。
双目运算符重载为成员函数

双目运算符 B

  • 如果要重载B为类成员函数,使之能够实现:
    表达式 oprd1 B oprd2, 其中oprd1为A类对象,则B应被重载为A类的成员函数,形参类型应该是oprd2所属的类型。
  • 经重载后,表达式oprd1 B oprd2 相当于oprd1.operator B(oprd2).
    即对象名oprd1.函数名B(参数)的调用形式。
将“+”运算重载为复数类的成员函数
  • 实现2个复数对象的加法运算,add 成员函数与 “+”运算符重载为成员函数。
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
	complex(double r=0.0,double i=0.0){real=r;imag=i;}//构造函数
	complex add(complex &c2); //add成员函数
	complex operator +(complex &c2); //+重载为成员函数
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
complex  complex::add(complex &c2) //通过成员函数实现
{	complex t;
	t.real=real+c2.real;
	t.imag=imag+c2.imag;
	return t;
}
complex complex::operator +(complex &c2)  //重载+运算符为成员函数
{	complex t;
	t.real=real+c2.real;
	t.imag=imag+c2.imag;
	return t;//相当于return complex(t.real,t.imag);
}
void complex::Show()
{	cout<<"("<<real<<","<<imag<<")"<<endl; 
}
int main()     //主函数
{	complex z1(1.5,2.8),z2(-2.3,3.4),z3,z4	z3=z1.add(z2);//成员函数调用
	cout<<"z3=";
	z3.Show();
	z4=z1+z2;//+运算符重载 
	cout<<"z4=";
	z4.Show();	
	return 0;
}

双目运算符重载为友元函数

将“+”运算符重载为复数类的成员函数
  • 实现2个复数对象的加法运算,add 成员函数与“+”运算符重载为友元函数。
#include <iostream>
using namespace std;
class complex	//复数类声明
{public:	//外部接口
	complex(double r=0.0,double i=0.0)//构造函数
	{real=r;imag=i;}
	friend complex add(complex &c1,complex &c2); //add2个复数友元函数	
	friend complex operator +(complex &c1,complex &c2); //+重载为友元函数
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
complex  add(complex &c1,complex &c2) //通过友元函数实现
{	complex t;
	t.real=c1.real+c2.real;
	t.imag=c1.imag+c2.imag;
	return t;
}
complex  operator +(complex &c1,complex &c2) //通过友元函数重载+运算符 
{	complex t;
	t.real=c1.real+c2.real;
	t.imag=c1.imag+c2.imag;
	return t;
}
void complex::Show()
{	cout<<"("<<real<<","<<imag<<")"<<endl; 
}
int main()     //主函数
{	complex z1(1.5,2.8),z2(-2.3,3.4),z3,z4	z3=add(z1,z2);//友元函数调用	cout<<"z3=";
	z3.Show();
	z4=z1+z2;//+运算符重载 
	cout<<"z4=";
	z4.Show();	
	return 0;
}

单目运算符重载为成员函数

  • 前置单目运算符 U

    • 如果要重载前置 U 为类成员函数,使之能够实现表达式U oprd,其中oprd 为A类对象,则U应被重载为A类的成员函数,无形参。
    • 经重载后,表达式U oprd相当于oprd.operator U ()
  • 后置单目运算符 U

    • 如果要重载后置U为类成员函数,使之能够实现表达式oprd U,其中 oprd 为A 类对象,U应被重载为A类的成员函数,且具有一个int 类型的参数。
    • 经重载后,表达式oprd U 相当于oprd.opreator U(0) // 参数0 为后置运算标志。
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
	complex(double r=0.0,double i=0.0){real=r;imag=i;}//构造函数
    complex operator ++(); //重载前置++运算符为成员函数
    complex operator ++(int); //重载后置++运算符为成员函数
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
complex complex::operator ++() //重载成员函数实现
{	complex t;
	t.real=real+1;
	t.imag=imag+1;
	real=real+1;
	imag=imag+1;
	return t;//相当于return complex(t.real,t.imag);
}
complex complex::operator ++(int) //重载成员函数实现
{	complex t;
	t.real=real;
	t.imag=imag;
	real=real+1;
	imag=imag+1;
	return t;//相当于return complex(t.real,t.imag);
}
void complex::Show()
{
	cout<<"("<<real<<","<<imag<<")"<<endl; 
}
int main()     //主函数
{complex z1(1.5,2.8),z2(1.5,2.8),z3,z4;
z3=++z1;//++前置运算符重载 
cout<<"z3=";
z3.Show();	
z4=z2++;//++后置运算符重载 
cout<<"z4=";
z4.Show();	
return 0;
}

单目运算符重载为友元函数

  • 前置单目运算符 U

    • 如果要重载 前置U 为类友元函数,使之能够实现表达式 U oprd,其中 U 应被重载为 A 类的成员函数,形参为oprd 所属类型。
    • 经重载后,表达式 U oprd 相当于 operator U(oprd)
  • 后置单目运算符U

    • 如果要重载后置U为类友元函数,使之能够实现表达式 oprd U ,其中U应被重载为 A 类的成员函数,有2个形参,其中一个是oprd所属类型,另一个是int 类型形参,但不必写形参名。
    • 经重载后,表达式 oprd U 相当于 operator U(oprd,0)。
    • //参数0只是后置运算标志
#include <iostream>
using namespace std;
class complex	//复数类声明
{
public:	//外部接口
	complex(double r=0.0,double i=0.0){real=r;imag=i;}//构造函数
    friend complex operator ++(complex &c); //重载前置++运算符为友元函数
    friend complex operator ++(complex &c,int); //重载后置++运算符为友元函数
	void Show();	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	
complex operator ++(complex &c) //重载友元函数实现
{	complex t;
	t.real=c.real+1;
	t.imag=c.imag+1;
	c.real=c.real+1;
	c.imag=c.imag+1;
	return t;//相当于return complex(t.real,t.imag);
}
complex operator ++(complex &c,int) //重载友元函数实现
{	complex t;
	t.real=c.real;
	t.imag=c.imag;
	c.real=c.real+1;
	c.imag=c.imag+1;
	return t;//相当于return complex(t.real,t.imag);
}
void complex::Show()
{
cout<<"("<<real<<","<<imag<<")"<<endl; 
}
int main()     //主函数
{complex z1(1.5,2.8),z2(1.5,2.8),z3,z4;
z3=++z1;//++前置运算符重载 
cout<<"z3=";
z3.Show();	
z4=z2++;//++后置运算符重载 
cout<<"z4=";
z4.Show();	
return 0;
}

参考:https://blog.youkuaiyun.com/PattyAndSmith/article/details/84341952

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值