所谓多态性是指发出同样的消息被不同类型的对象接收时导致完全不同的行为。这里所说的消息主要是指对类的成员函数的调用,而不同的行为是指不同的实现。利用多态性,用户只需发送一般形式的消息,而将所有的实现留给接收消息的对象。对象根据所接收到的消息而做出相应的动作(即操作)。
函数重载和运算符重载是简单一类多态性。
所谓函数重载简单地说就是赋给同一个函数名多个含义。具体地讲,C++中允许在相同的作用域内以相同的名字定义几个不同实现的函数,可以是成员函数,也可以是非成员函数。但是,定义这种重载函数时要求函数的参数或者至少有一个类型不同,或者个数不同。而对于返回值的类型没有要求,可以相同,也可以不同。那种参数个数和类型都相同,仅仅返回值不同的重载函数是非法的。因为编译程序在选择相同名字的重载函数时仅考虑函数表,这就是说要靠函数的参数表中,参数个数或参数类型的差异进行选择。
由此可以看出,重载函数的意义在于它可以用相同的名字访问一组相互关联的函数,由编译程序来进行选择,因而这将有助于解决程序复杂性问题。如:在定义类时,构造函数重载给初始化带来了多种方式,为用户提供更大的灵活性
运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。运算符重载的实质就是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这个过程是在编译过程中完成的。
一、运算符重载的作用
运算符重载为类的用户提供了更直观的接口,使类类型的对象也可以像普通变量一样进行运算符的表达式运算。运算符重载允许C/C++的运算符在用户定义类型(类)上拥有一个用户定义的意义。
二、运算符重载的规则
(1)C++中的运算符除了少数几个以外,全部可以重载,而且只能重载已有的运算符。
可以重载的运算符有:
算术运算符:+,-,*,/,%,++,--;
位操作运算符:&,|,~,^,<<,>>
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
不能重载的运算符只有5个:
类属关系运算符“.”,成员指针运算符“*”,作用域分辨符“::”,sizeof运算符和三目运算符“?:”。
(2)重载之后运算符的优先级和结合性都不变。
(3)四个“不能改变”
·不能改变运算符操作数的个数;
·不能改变运算符原有的优先级;
·不能改变运算符原有的结合性;
·不能改变运算符原有的语法结构。
(4)至少要有一个操作对象是自定义类型。
(5)重载的运算符含义必须清楚,不能有二义性。
三、运算符重载的2种方法
(1)运算符重载为成员函数
a)对于双目运算符op,如果要重载op为某类的成员函数,使之能够实现表达式 k op t,其中k为A类的对象,则应当把op重载为A类的成员函数,该函数只有一个形参,形参的类型是t所属的类型。经过这样重载之后,表达式 k op t 就相当于函数调用k.operator op( t )
b)对于前置单目运算符U(如负号“-”),若要重载U为类的成员函数,用来实现表达式
U oprd,其中oprd为A类的对象,则U应当重载为A类的成员函数,且该函数不带形参。经过重载之后,表达式U oprd 就相当于函数调用oprd.operator U()。
c)后置运算符“++”和“--”,若要将它们重载为类的成员函数,用来实现表达式oprd++或oprd--,其中oprd为A类的对象,那么就应当重载这2个运算符为A类的成员函数,这时函数要带有一个整型(int)形参。重载之后,表达式 oprd ++ 和 oprd -- 就分别相当于函数调用oprd.operator ++(0) 和 oprd.operator --(0)。
(2)运算符重载为友元函数
a)对于双目运算符op,如果它的一个操作数为类A的对象,就可以将op重载为A类的友元函数,该函数有两个形参,其中一个形参的类型是A类。经过这样的重载之后,表达式k op t就相当于函数调用operator op( k, t )
b)对于前置单目运算符U(如负号“-”),若要实现表达式 U oprd 其中oprd为A类的对象,则U可以重载为A类的友元函数,函数的形参为A类的对象oprd。经过重载之后,表达式
U oprd 就相当于函数调用operator U( oprd )
c)对于后置运算符“++”和“--”,如果要实现表达式 oprd ++ 或 oprd --, 其中oprd为A类的对象,那么运算符就可以重载为A类的友元函数,这时函数的形参有两个,一个是A类的对象oprd,另一个是整型(int)形参。第二个参数是用于与前置运算符函数相区别的。重载之后,表达式oprd ++ 和 oprd -- 就分别相当于函数调用operator ++ (oprd, 0)
和operator -- (oprd, 0)。
(3)两种重载方法的比较
一般说来,单目运算符最好被重载为成员;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便,但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。因为,它如果被重载为友元函数,将会出现与赋值语义不一致的地方。
四、特殊运算符的重载
1).下标运算符重载
由于C语言的数组中并没有保存其大小,因此,不能对数组元素进行存取范围的检查,无法保证给数组动态赋值不会越界。利用C++的类可以定义一种更安全、功能强的数组类型。为此,为该类定义重载运算符[]。
下面先看看一个例子:
#include <iostream.h>
class CharArray //数组类
{
public:
CharArray(int l)
{
Length = l;
Buff = new char[Length];
}
~CharArray()
{
delete Buff;
}
int GetLength()
{
return Length;
}
char & operator [](int i);
private:
int Length;
char * Buff;
};
char & CharArray::operator [](int i)
{
static char ch = 0;
if(i<Length && i>=0)
{
return Buff[i];
}
else
{
cout<<"\nIndex out of range.";
return ch;
}
}
void main()
{
int cnt;
CharArray string1(6);
char * string2 = "string";
for(cnt=0; cnt<8; cnt++)
{
string1[cnt] = string2[cnt];
}
cout<<"\n";
for(cnt=0; cnt<8; cnt++)
{
cout<<string1[cnt];
}
cout<<"\n";
cout<<string1.GetLength()<<endl;
}
该数组类的优点如下:
(1) 其大小不必是一个常量。
(2) 运行时动态指定大小可以不用运算符new和delete。
(3) 当使用该类数组作函数参数时,不必分别传递数组变量本身及其大小,因为该对象中已经保存大小。
在重载下标运算符函数时应该注意:
(1) 该函数只能带一个参数,不可带多个参数。
(2) 不得重载为友元函数,必须是非static类的成员函数。
2). 重载增1减1运算符
增1减1运算符是单目运算符。它们又有前缀和后缀运算两种。为了区分这两种运算,将后缀运算视为双目运算符。表达式
obj++或obj--
被看作为:
obj++0或obj--0
下面举一例子说明重载增1减1运算符的应用。
#include <iostream.h>
class counter
{
public:
counter() { v=0; }
counter operator ++();
counter operator ++(int );
void print()
{
cout<<v<<endl;
}
private:
unsigned v;
};
counter counter::operator ++()
{
v++;
return *this;
}
counter counter::operator ++(int)
{
counter t;
t.v = v++;
return t;
}
void main()
{
counter c;
for(int i=0; i<8; i++)
{
c++;
}
c.print();
for(i=0; i<8; i++)
{
++c;
}
c.print();
}
3). 重载函数调用运算符
可以将函数调用运算符()看成是下标运算[]的扩展。函数调用运算符可以带0个至多个参数。下面通过一个实例来熟悉函数调用运算符的重载。
#include <iostream.h>
class F
{
public:
double operator ()(double x, double y) const;
};
double F::operator ()(double x, double y) const
{
return (x+5)*y;
}
void main()
{
F f;
cout<<f(1.5, 2.2)<<endl;
}
要注意的是:对于赋值操作符的重载,要解除A的内存分配,再制作A的副本。但解除A的内存分配后,就没有可供复制的了,实现代码应确定等号左边的调用对象是否与等号右边的对象向同,测试这个特例,赋值运算符应是防故障的。
转自:http://hi.baidu.com/clfx/blog/item/02c3ed11db0e2ec3a6ef3f61.html
分享到:
相关推荐
在给定的实例中,你将学习如何实际应用这些概念,通过成员函数和非成员函数重载C++运算符,以及如何使用友元函数来实现特定的运算行为。通过练习和理解这些例子,你将更好地掌握C++中运算符重载和友元函数的使用。
详细介绍 C++运算符重载 的PPT 文中部分内容: 下标运算符“[ ]”重载 C++把下标运算符[ ]看成一个双目运算符,其操作数为<基本表达式>和<表达式>,对应的运算符为operator[ ],必须重载为一个成员函数。对于下标...
C++允许重载的运算符和不允许...C++运算符重载的规则 C++对运算符重载定义了如下几条规则。 1) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。 例如,有人觉得BASIC中用“**“作为幂运算符很方便
在C++编程语言中,运算符重载是一个关键特性,它允许我们为已存在的运算符赋予新的含义,以便在自定义类型上使用...通过对C++运算符重载的深入理解和实践,你可以编写出更加自然、直观的代码,提升代码质量和可维护性。
中国农业大学C++课程课件,信息与电气工程学院学生专用。
"Visual C++ 运算符重载详细总结" Visual C++ 运算符重载是指在 C++ 编程语言中对已有的运算符进行重新定义,以适应自定义的数据类型和操作。这种技术可以使得程序员能够使用熟悉的运算符来操作自定义的数据类型,...
C++运算符重载 C++运算符重载是面向对象程序设计中的一种重要概念,它允许开发者重新定义运算符的行为,以符合特定类的需求。运算符重载是通过在类中定义特殊的成员函数或友元函数来实现的,这些函数的名称以...
"c++运算符重载矩阵运算" c++运算符重载矩阵运算是指在c++语言中对矩阵进行运算的操作,包括加、减、乘、转置、赋值等操作。这些操作都是通过重载运算符来实现的。 首先,我们需要定义一个Matrix类,该类有三个...
C++运算符重载的课件 C++运算符重载是C++程序设计中一个非常重要的概念,它允许用户自定义的数据类型以一种更简洁的方式工作,使得代码更加简洁易读。运算符重载使得用户可以定义自己的运算符,以便更好地描述问题...
C++运算符重载函数作为类成员函数和友元函数 C++运算符重载函数是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。运算符重载实质上是函数的重载。重载运算符的...
C++运算符重载学习笔记 C++类和对象是面向对象编程的基础概念。运算符重载是C++中的一种重要机制,允许开发者重新定义已有的运算符,赋予其新的功能,以适应不同的数据类型。在本文中,我们将详细介绍C++运算符重载...
### C++运算符重载详解 #### 一、前言 C++允许用户自定义类或结构体,并为这些类型重载内置运算符,从而使得这些类型能够像内置类型一样使用标准运算符进行操作。本篇文章将通过三个具体的示例来深入探讨C++中的...
C++运算符重载是C++中一个强大的特性,它允许程序员为自定义类型定义运算符的行为。在C++中,运算符重载有三种主要形式:成员函数、友元函数以及普通函数。每种形式都有其特定的使用场景和优缺点。 1. 成员函数重载...
C++运算符重载 C++语言提供了运算符重载机制,允许程序员对已有的运算符赋予新的含义,使其应用于用户自定义的类。运算符重载是对已有的运算符赋予多重含义,同时保持其原有的优先级和结合性。 什么是运算符重载?...
C++ 运算符重载 本节主要介绍 C++ 运算符重载的概念、语法和应用。运算符重载是 C++ 的一个重要特性,允许开发者重新定义运算符的行为,以适应不同的需求。 首先,运算符重载的语法形式如下:返回类型 operator@...
### C++运算符重载教学和编程中易被忽视的问题 #### 1. 二元运算符重载为类成员函数时易忽视的问题及解决方法 以复数类为例,在实现复数相加的过程中,很容易忽略一个重要的设计原则:**当一个二元运算符(如加法...
首先,我们要理解C++中的运算符重载。运算符重载允许我们在不同的上下文中为同一个运算符赋予不同的含义,这在处理自定义数据类型如矩阵时非常有用。例如,我们可以通过重载"+"运算符来实现矩阵的相加,重载"-...