C++ operator关键字(重载操作符)的用法详解

operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名。

这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算符的使用方法与其原来一致,另一方面扩展其功能只能通过函数的方式(c++中,“功能”都是由函数实现的)。

一、为什么使用操作符重载?

对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class,如果想支持基本操作,比如比较大小,判断是否相等,等等,则需要用户自己来定义关于这个操作符的具体实现。比如,判断两个人是否一样大,我们默认的规则是按照其年龄来比较,所以,在设计person 这个class的时候,我们需要考虑操作符==,而且,根据刚才的分析,比较的依据应该是age。那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了用户定义的数据类型class,所以,需要用户自己来提供该参数版本的实现。

二、如何声明一个重载的操作符?

A:  操作符重载实现为类成员函数

重载的操作符在类体中被声明,声明方式如同普通成员函数一样,只不过他的名字包含关键字operator,以及紧跟其后的一个c++预定义的操作符。

可以用如下的方式来声明一个预定义的==操作符:

class person{
private:
  int age;
  public:
  person(int a){
    this->age=a;
  }
  inline bool operator == (const person &ps) const;
};

实现方式如下:

inline bool person::operator==(const person &ps) const
{

   if (this->age==ps.age)
    return true;
   return false;
}

调用方式如下:

#include
using namespace std;
int main()
{

 person p1(10);
 person p2(20);
 if(p1==p2) cout<<”the age is equal!”< return 0;
}

这里,因为operator ==是class person的一个成员函数,所以对象p1,p2都可以调用该函数,上面的if语句中,相当于p1调用函数==,把p2作为该函数的一个参数传递给该函数,从而实现了两个对象的比较。

B:操作符重载实现为非类成员函数(全局函数)

对于全局重载操作符,代表左操作数的参数必须被显式指定。例如:

#include
#include
using namespace std;
class person
{
public:
int age;
public:
};

bool operator==(person const &p1 ,person const & p2)

//满足要求,做操作数的类型被显示指定
{
if(p1.age==p2.age)
return true;
return false;
}
int main()
{
person rose;
person jack;
rose.age=18;
jack.age=23;
if(rose==jack)
cout<<"ok"< return 0;
}

C:如何决定把一个操作符重载为类成员函数还是全局名字空间的成员呢?

①如果一个重载操作符是类成员,那么只有当与他一起使用的左操作数是该类的对象时,该操作符才会被调用。如果该操作符的左操作数必须是其他的类型,则操作符必须被重载为全局名字空间的成员。

②C++要求赋值=,下标[],调用(), 和成员指向-> 操作符必须被定义为类成员操作符。任何把这些操作符定义为名字空间成员的定义都会被标记为编译时刻错误。

③如果有一个操作数是类类型如string类的情形那么对于对称操作符比如等于操作符最好定义为全局名字空间成员。

D:重载操作符具有以下限制:

(1)只有C++预定义的操作符集中的操作符才可以被重载;

(2)对于内置类型的操作符,它的预定义不能被改变,应不能为内置类型重载操作符,如,不能改变int型的操作符+的含义;

(3) 也不能为内置的数据类型定义其它的操作符;

(4) 只能重载类类型或枚举类型的操作符;

(5) 重载操作符不能改变它们的操作符优先级;

(6) 重载操作符不能改变操作数的个数;

(7) 除了对( )操作符外,对其他重载操作符提供缺省实参都是非法的;

E: 注意点

(1)后果载操操作符首先要确定它的返回值是左值,还是右值,如果是左值最返回引用,如果是右值那就直接返回值;

(2) +号等这样的操作符没有对象可以容纳改变后值,对于这样的情况最好返回数值,否则只能要操作符体内创建临时对象用于容纳改变后的值,如果在堆中创建临时对象返回指针或者引用,在操作符函数体外还需要释放它,如果返回的对象而不是引用或者指针,那么效率是比较低的。如果返回的是数值,最好在该类的构造函数中增加对该类型数值的转换函数,如:返回值是int类型,那么最好有一个int类型作为参数的构造函数。

(3)在增量运算符中,放上一个整数形参,就是后增量运行符,它是值返回,对于前增量没有形参,而且是引用返回,示例:

class Test

{

  public:

  Test(x=3){ m_value = x}

  Test &operator ++();  //前增量

  Test &operator ++(int);//后增量

private:

  Int m_value:

};

Test &Test::operator ++()

{

  m_value ++;  //先增量

  return *this; //返回当前对象

}

Test Test::operator ++(int)

{

  Test tmp(*this); //创建临时对象

  m_value ++;    //再增量

  return temp;   //返回临时对象

}

(4)因为强制转换是针对基本数据类型的,所以对类类型的转换需自定义;

(5) 转换运行符重载声明形式:operator 类型名();它没有返回类型,因为类型名就代表了它的返回类型,所以返回类型显得多余。

(6)一般来说,转换运算符与转换构造函数(即带一个参数的构造函数)是互逆的,如有了构造函数Test(int),那么最好有一个转换运算符int()。这样就不必提供对象参数重载运算符了,如Test a1(1);Test a2(2); Test a3; a3 = a1+a2;就不需要重载+号操作符了,因为对于a1+a2的运算,系统可能会先找有没有定义针对Test的+号操作符,如果没有,它就会找有没有针对Test类转换函数参数类型的+号操作符(因为可以将+号运行结果的类型通过转换函数转换为Test对象),因为Test类有个int类型的参数,对于int类型有+操作符,所以a1+a2真正执行的是Test(int(a1) + int(a2));即Test(3);

(7)对于转换运算符,还有一个需要注意的地方就是,如果A类中有以B为参数的转换函数(构造函数),那B中不能有A的转换运算符,不然就存在转换的二义性,如:

class A{A(B&){…}}; class B{ operator A(){…}};

那么以下语句就会有问题:

B b; A(b);//A(b)有就可能是A的构造函数,也可以是B的转换运算符

以上就是小编为大家带来的C++ operator关键字(重载操作符)的用法详解全部内容了,希望大家多多支持我们~

(0)

相关推荐

  • 浅谈C++虚重载操作符 virtual operator= 的使用方法

    C++中虚操作符和其他虚函数的规则一样,操作符可以为虚函数,进行动态绑定, 虽然这种情况并不多见.本文以赋值操作符operator=举例. 派生类中要重定义基类虚函数,要注意参数必须为基类引用类型,否则与基类中虚函数是完全不同的,无法进行预期的动态绑定. 派生类除了重定义基类的虚操作符,还要定义自身的操作符重载.即派生层次每增加一层,理论上派生类就需要多定义一个操作符重载. 以下程序使用引用reference,通过指针调用赋值操作符(例:*p = value)情况是一样的. #include <

  • C++ 基础编程之十进制转换为任意进制及操作符重载

    C++ 基础编程之十进制转换为任意进制及操作符重载 最近学习C++ 的基础知识,完成十进制转换为任意进制及操作符重载,在网上找的不错的资料,这里记录下, 实例代码: #include<iostream> #include<vector> #include<limits> using namespace std; using std::iterator; ///<summary> ///十进制转换为任意进制,为了熟悉操作符,也加了操作符重载. ///包括自增(

  • C++输入输出操作符重载的深入分析

    操作符的重载有一些规则: 1. 重载操作符必须具有一个类类型或枚举类型操作数.这条规则强制重载操作符不能重新定义用于内置类型对象的操作符的含义.如:int operator+(int, int), 不可以    2. 为类设计重载操作符的时候,必须选择是将操作符设置为类成员还是普通非成员函数.在某些情况下,程序没有选择,操作符必须是成员:在另外一些情况下,有些经验可以指导我们做出决定.下面是一些指导:a. 赋值(=),下标([]),调用(())和成员访问箭头(->)等操作符必须定义为成员,将这些

  • C++中的三大函数和操作符重载(Boolan)

    C++中三大函数: 析构函数 复制构造函数 =操作符(copy assignment operator) 这三个特殊的成员函数如果程序员没有实现,编译器将提供默认的实现方式. 析构函数: 形如-foo_t(),函数名和构造函数相同,前面加-,如果对象是自由变量创建,析构函数将在脱离作用域时调用.如果对象是通过new操作符创建的,则通过delete操作符调用析构函数. 复制构造函数: 形如foo_t(const foo_t& foo),以下情况复制构造函数均会被调用: 当对象按值返回时候(retu

  • 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++中复制构造函数和重载赋值操作符总结

    前言 这篇文章将对C++中复制构造函数和重载赋值操作符进行总结,包括以下内容: 1.复制构造函数和重载赋值操作符的定义: 2.复制构造函数和重载赋值操作符的调用时机: 3.复制构造函数和重载赋值操作符的实现要点: 4.复制构造函数的一些细节. 复制构造函数和重载赋值操作符的定义 我们都知道,在C++中建立一个类,这个类中肯定会包括构造函数.析构函数.复制构造函数和重载赋值操作:即使在你没有明确定义的情况下,编译器也会给你生成这样的四个函数.例如以下类: 复制代码 代码如下: class CTes

  • C++ new、delete(new[]、delete[])操作符重载需要注意的问题

    new.delete(new[].delete[])操作符的重载需要注意: 1.重载的 new.delete(或者 new[].delete[])操作符必须是类的静态成员函数(为什么必须是静态成员函数,这很好理解,因为 new 操作符被调用的时候,对象还未构建)或者是全局函数,函数的原型如下: 复制代码 代码如下: void* operator new(size_t size) throw(std::bad_alloc); // 这里的 size 为分配的内存的总大小 void* operato

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

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

  • C++之CNoTrackObject类和new delete操作符的重载实例

    本文实例讲述了C++中CNoTrackObject类和new delete操作符的重载,分享给大家供大家参考.具体如下: 头信息: 复制代码 代码如下: class CNoTrackObject{  public: //在此出过错,没有加public 默认为类的私有变量,MyThreadData继承这个类后也无法访问成员变量      void* operator new(size_t nSize);      void operator delete(void*);      virtual

  • C++ operator关键字(重载操作符)的用法详解

    operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名. 这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算符的使用方法与其原来一致,另一方面扩展其功能只能通过函数的方式(c++中,"功能"都是由函数实现的). 一.为什么使用操作符重载? 对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class,如果想支持基本操作,比如比较大小,判断是否相等,

  • Java中volatile关键字的作用与用法详解

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile 关键字作用是,使系统中所有线程对该关键字修饰的变量共享可见,可以禁止线程的工作内存对volatile修饰的变量进行缓存. volatile 2个使用场景: 1.可见性:Java提供了volatile关键字来保证可见性. 当一个共享变量被volatile修饰时,它会保证修

  • Postgresql中LIKE和ILIKE操作符的用法详解

    LIKE和ILIKE操作符可以模糊匹配字符串,LIKE是一般用法,ILIKE匹配时则不区分字符串的大小写. 它们需要结合通配符使用,下面介绍两种常用的通配符. %:百分号用于匹配字符串序列,可匹配任意组合: _:下划线用于匹配任何单一字符. 举例来说明LIKE和ILIKE操作符的区别. 先创建一张数据表table1,包含两列:id列和name列,代码如下: create table table1(id int, name varchar); insert into table1 values(1

  • Java switch关键字原理及用法详解

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • MySQL中ESCAPE关键字的用法详解

    MySQL转义 转义即表示转义字符原来的语义,一个转义字符的目的是开始一个字符序列,使得转义字符开头的该字符序列具有不同于该字符序列单独出现时的语义. MySQL中,转义字符以"\"开头,编程中常见的转义字符,在MySQL均是有效的,在此不做赘述和讨论.在此,主要通过"%" 和 "_"来对ESCAPE关键字的作用进行说明. %:匹配任意多个字符. _:匹配单一字符. 如果我们要匹配"%"或者"_"时,就必须

  • C++之重载 重定义与重写用法详解

    一.重载(重载函数) 重载函数是C++为了方便使用,允许在同一范围中(一个类中)声明几个功能类似的同名函数,但是这些同名函数的形参(指参数的个数.类型或者顺序至少有一个)必须不同 1.代码实现在一个类中fun()函数的重载: #include<iostream> using namespace std; class Base { public: void fun() { cout << "Base::fun()" << endl; } void fu

  • Java instanceof关键字用法详解及注意事项

    instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为: boolean result = obj instanceof Class 其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false. 注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,

  • Java super关键字的用法详解

    目录 super关键字的三种用法: 1. super.成员变量 2. super.成员方法 3. super():调用父类中的构造方法 3.1.1 隐式调用父类无参数构造方法super() 3.1.2 显式调用父类有参数构造方法super(id) super关键字作用:在子类内部调用父类对象 基础语法: 1.在类的继承中,当子类继承了父类, 在构造子类的时候,一定要先帮助父类进行构造: 2. 调用super()必须写在子类构造方法的第一行,以保证在执行任何动作前,对象已经完成了初始化,否则编译不

  • c语言static关键字用法详解

    目录 1.static修饰全局变量 2.static修饰函数 3.static修饰局部变量 总结: 1.static修饰全局变量 我们创建两个源文件,一个test.c,一个main.c 现在我们在test.c文件下定义一个全局变量 int g_val = 100; 我们在main.c下进行调用打印g_val我们能访问到g_val吗? 答案是可以的 如果给g_val加上static修饰我们还能再main.c下访问到吗? static int g_val = 100; 这时候答案是不行的! 因此我们

  • C语言const关键字的用法详解

    目录 1 介绍 1.1 const修饰变量 1.2 const修饰数组 1.3 const修饰指针 1.4 const修饰函数参数 2 const对程序的影响 3 总结 1 介绍 const关键字是constant的缩写,翻译为常量.常数.在C语言中const的作用很强大,它可以修饰变量.数组.指针.函数参数等. 1.1 const修饰变量 const修饰变量,表示希望此变量具有只读性,防止被直接直接修改. //const关键字是constant的缩写,翻译为常量.常数. //在C语言中cons

随机推荐