原创博文,转载请标明出处--周学伟 http://www.cnblogs.com/zxouxuewei/

c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程序更加简洁、高效。

在c++中不止函数可以重载,运算符也可以重载。由于一般数据类型间的运算符没有重载的必要,所以运算符重载主要是面向对象之间的。

1.一般运算符重载

在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。

    class A
{
public:
A(int d):data(d){}
A operator+(A&);//成员函数
A operator-(A&);
A operator*(A&);
A operator/(A&);
A operator%(A&);
friend A operator+(A&,A&);//友元函数
friend A operator-(A&,A&);
friend A operator*(A&,A&);
friend A operator/(A&,A&);
friend A operator%(A&,A&);
private:
int data;
};
//成员函数的形式
A A::operator+(A &a)
{
return A(data+a.data);
}
A A::operator-(A &a)
{
return A(data-a.data);
}
A A::operator*(A &a)
{
return A(data*a.data);
}
A A::operator/(A &a)
{
return A(data/a.data);
}
A A::operator%(A &a)
{
return A(data%a.data);
}
//友元函数的形式
A operator+(A &a1,A &a2)
{
return A(a1.data+a2.data);
}
A operator-(A &a1,A &a2)
{
return A(a1.data-a2.data);
}
A operator*(A &a1,A &a2)
{
return A(a1.data*a2.data);
}
A operator/(A &a1,A &a2)
{
return A(a1.data/a2.data);
}
A operator%(A &a1,A &a2)
{
return A(a1.data%a2.data);
}
//然后我们就可以对类的对象进行+、-、*、/了。
void main(void)
{
   A a1(),a2(),a3();
  a1=a2.operator+(a3);
}

  eg:

/***************友元函数重载1******************/
#include <iostream>
using namespace std; typedef unsigned int Uint32; class testStruction
{
public:
    testStruction(Uint32 hundred)
        :hundredValue(hundred){}     friend testStruction operator +(const testStruction&, const testStruction&);
    friend testStruction operator -(const testStruction&, const testStruction&);     void displayValue(); private:
    Uint32 hundredValue;
}; void testStruction::displayValue()
{
    cout <<"hundredValue = "<<this->hundredValue<<endl;
} testStruction operator +(const testStruction& str1, const testStruction& str2)
{
    return (str1.hundredValue + str2.hundredValue);
} testStruction operator -(const testStruction& str1, const testStruction& str2)
{
    return (str1.hundredValue - str2.hundredValue);
} int main()
{
    testStruction structUserA(1003),structUserB(1008);     structUserA = structUserA + structUserB;
    structUserA.displayValue();     return 0;
} /*********成员函数运算符重载1****************/
#include <iostream>
using namespace std; typedef unsigned int Uint32; class testStruction
{
public:
    testStruction(Uint32 hundred)
        :hundredValue(hundred){}     testStruction operator +(const testStruction&);
    testStruction operator -(const testStruction&);     void displayValue(); private:
    Uint32 hundredValue;
}; void testStruction::displayValue()
{
    cout <<"hundredValue = "<<this->hundredValue<<endl;
} testStruction testStruction::operator +(const testStruction& str1)
{
    return testStruction(this->hundredValue + str1.hundredValue);
}
testStruction testStruction::operator -(const testStruction& str1)
{
    return testStruction(this->hundredValue - str1.hundredValue);
} int main()
{
    testStruction structUserA(1003);
    testStruction structUserB(1000);     structUserA = structUserA - structUserB;
    structUserA.displayValue();     structUserA = structUserA + structUserB;
    structUserA.displayValue();     return 0;
}

2.关系运算符重载

因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,<,>,<=,>=。

    bool operator == (const A& );
bool operator != (const A& );
bool operator < (const A& );
bool operator <= (const A& );
bool operator > (const A& );
bool operator >= (const A& );

  eg:

#include <iostream>
using namespace std; typedef unsigned int Uint32; class testStruction
{
public:
testStruction(Uint32 hundred)
:hundredValue(hundred){} friend bool operator >(const testStruction&, const testStruction&);
friend bool operator <(const testStruction&, const testStruction&); void displayValue(); private:
Uint32 hundredValue;
}; void testStruction::displayValue()
{
cout <<"hundredValue = "<<this->hundredValue<<endl;
} bool operator >(const testStruction& str1, const testStruction& str2)
{
return (str1.hundredValue > str2.hundredValue) ?true :false;
} bool operator <(const testStruction& str1, const testStruction& str2)
{
return (str1.hundredValue < str2.hundredValue) ?true :false;
} int main()
{
testStruction structUserA(),structUserB(); if (structUserA > structUserB)
cout <<"structUserA > structUserB"<<endl;
else
cout <<"structUserA < structUserB"<<endl; if (structUserA < structUserB)
cout <<"structUserA < structUserB"<<endl;
else
cout <<"structUserA > structUserB"<<endl; return ;
}

3.逻辑运算符重载

    bool operator || (const A& );
bool operator && (const A& );
bool operator ! ();

4.单目运算符重载

这里的+、-是正负的意思,放在对象前面。

    A& operator + ();
A& operator - ();
A* operator & ();
A& operator * ();

5.自增减运算符重载

++和–根据位置的不同有四种情况,都可以重载。

    A& operator ++ ();//前置++
A operator ++ (int);//后置++
A& operator --();//前置--
A operator -- (int);//后置--

  EG:

  

#include <iostream>
using namespace std; typedef unsigned int Uint32; class testStruction
{
public:
testStruction(Uint32 hundred)
:hundredValue(hundred){} testStruction& operator ++();
testStruction operator ++(int); void displayValue(); private:
Uint32 hundredValue;
}; void testStruction::displayValue()
{
cout <<"hundredValue = "<<this->hundredValue<<endl;
} testStruction& testStruction::operator ++()
{
++hundredValue;
return *this;
} testStruction testStruction::operator ++(int)
{
testStruction temp(*this);
++hundredValue;
return temp;
} int main()
{
testStruction structUserA(),structUserB(); testStruction C = structUserA++;
C.displayValue(); testStruction D = ++structUserB;
D.displayValue(); return ;
}

6.位运算符重载

按位操作。

    A operator | (const A& );
A operator & (const A& );
A operator ^ (const A& );
A operator << (int i);
A operator >> (int i);
A operator ~ ();

7.赋值运算符重载

没有=哦。

    A& operator += (const A& );
A& operator -= (const A& );
A& operator *= (const A& );
A& operator /= (const A& );
A& operator %= (const A& );
A& operator &= (const A& );
A& operator |= (const A& );
A& operator ^= (const A& );
A& operator <<= (int i);
A& operator >>= (int i);

8.内存运算符重载

    void *operator new(size_t size);
void *operator new(size_t size, int i);
void *operator new[](size_t size);
void operator delete(void*p);
void operator delete(void*p, int i, int j);
void operator delete [](void* p);

9.特殊运算符重载

上面的运算符重载都有两种方式,而下面的运算符只能用一种,特殊吧。 这些运算符的重载只能是成员函数。

    A& operator = (const A& );
char operator [] (int i);//返回值不能作为左值
const char* operator () ();
T operator -> ();
//类型转换符
operator char* () const;
operator int ();
operator const char () const;
operator short int () const;
operator long long () const;
//还有很多就不写了

而这些只能以友元函数的形式重载

    friend inline ostream &operator << (ostream&, A&);//输出流
friend inline istream &operator >> (istream&, A&);//输入流

10.总结

两种重载方式的比较:

  • 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
  • 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
  • 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。 C++提供4个类型转换函数:reinterpret_cast(在编译期间实现转换)、const_cast(在编译期间实现转换)、stactic_cast(在编译期间实现转换)、dynamic_cast(在运行期间实现转换,并可以返回转换成功与否的标志)。
  • 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
  • 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
  • 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部 类型的对象,该运算符函数必须作为一个友元函数来实现。
  • 当需要重载运算符具有可交换性时,选择重载为友元函数。

注意事项:

  1. 除了类属关系运算符”.“、成员指针运算符”.*“、作用域运算符”::“、sizeof运算符和三目运算符”?:“以外,C++中的所有运算符都可以重载。
  2. 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
  3. 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
  4. 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
  5. 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
  6. 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。

c++运算符重载---20的更多相关文章

  1. C#高级编程笔记2016年10月12日 运算符重载

    1.运算符重载:运算符重重载的关键是在对象上不能总是只调用方法或属性,有时还需要做一些其他工作,例如,对数值进行相加.相乘或逻辑操作等.例如,语句if(a==b).对于类,这个语句在默认状态下会比较引 ...

  2. YTU 2617: B C++时间类的运算符重载

    2617: B C++时间类的运算符重载 时间限制: 1 Sec  内存限制: 128 MB 提交: 284  解决: 108 题目描述 C++时间类的运算符重载 定义一个时间类Time,其数据成员为 ...

  3. swift:高级运算符(位运算符、溢出运算符、优先级和结合性、运算符重载函数)

    swift:高级运算符 http://www.cocoachina.com/ios/20140612/8794.html 除了基本操作符中所讲的运算符,Swift还有许多复杂的高级运算符,包括了C语和 ...

  4. C++之运算符重载(1)

    在前一节中曾提到过,C++中运行时的多态性主要是通过虚函数来实现的,而编译时的多态性是由函数重载和运算符重载来实现的.这一系列我将主要讲解C++中有关运算符重载方面的内容.在每一个系列讲解之前,都会有 ...

  5. C#语言特性-运算符重载

    一.C#当中可以进行重载和不可重载的运算符: 1.简单的说明: 1.从上图中可以看到,可以重载的和不可以进行重载的运算符,比较特殊的是第二行和倒数第三行,的运算符,为什么会说它们特殊,是因为(第三行) ...

  6. C++之------运算符重载

    ①  什么是运算符重载? 何为C++的运算符重载呢? 其实就是运算符给它重新赋予新的含义或者多重含义.让它有另外一种新的功能. 为什么需要运算符重载? 面向对象中为了实现类的多态性,我们就引用了运算符 ...

  7. C++学习之运算符重载的总结

    C++学习之运算符重载的总结              运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生,C++为运算符重载提供了一种方法,即运算符重载函数 ...

  8. C++ Primer笔记10_运算符重载_赋值运算符_进入/输出操作符

    1.颂值运营商 首先来福值运算符引入后面要说的运算符重载.上一节说了构造函数.拷贝构造函数:一个类要想进行更好的控制.须要定义自己的构造函数.拷贝构造函数.析构函数.当然,还有赋值运算符.常说的三大函 ...

  9. 从零开始学C++之运算符重载(三):完善String类([]、 +、 += 运算符重载)、>>和<<运算符重载

    在前面文章中使用过几次String类的例子,现在多重载几个运算符,更加完善一下,并且重载流类运算符. []运算符重载 +运算符重载 +=运算符重载 <<运算符重载 >>运算符重 ...

随机推荐

  1. AT24Cxx(EEPROM)子系统

    1.配置内核 打开I2C功能: 打开杂项设备,该选项打开后,EEPROM也就打开了. 2. 修改代码 修改文件: linux/arch/arm/mach-s3c2440/mach-smdk2440.c ...

  2. Route学习笔记之Area的Route注册

    前一段时间接触了MVC的Area可以将模型.控制器和视图分成各个独立的节点.分区之后,区域路由注册的需求就出来了. 默认的 在MVC项目上右键添加区域之后,在文件夹下会自动添加一个FolderName ...

  3. 【C】——setvbuf(scanf内存溢出问题)

    下面设置了一个长度为20的缓存区,循环对value进行赋值并输出: #include<stdio.h> #define BUFSIZE 20 int main(int argc, char ...

  4. 虚拟机创建及安装ELK

    虚拟机创建及安装ELK 作者:高波 归档:学习笔记 2018年5月31日 13:57:02 快捷键: Ctrl + 1    标题1 Ctrl + 2    标题2 Ctrl + 3    标题3 C ...

  5. mybatis example 使用AND 和OR 联合查询

    mybatis example 使用AND 和OR 联合查询 ViewPsmsgconsultExample example=new ViewPsmsgconsultExample(); ViewPs ...

  6. 【IntelliJ IDEA】idea上提交代码到GitHub,已经提交了 但是GitHub上却没有的解决办法

    摘要: 今天提交idea上的代码到GitHub,提交过程已经完成, 在版本控制的Log中可以看到,已经将这一部分都提交更新了    在版本控制的Local Changes中已经看不到提交过的代码了   ...

  7. Linux中添加快捷

    执行操作比较快捷: 1.R3 CGP平台下OMU系统中: Linux 版本:2.6.16.60-0.21-bigsmp vi /etc/profile 2.R2 Linux版本2.6.5-7.244- ...

  8. Android Studio错误提示:Gradle project sync failed. Basic functionality (eg. editing, debugging) will not work properly

    Android Studio中出现提示: Gradle project sync failed. Basic functionality (eg. editing, debugging) will n ...

  9. Java 之 File

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  10. Relu的理解

    ReLU上的花样 CNN出现以来,感觉在各个地方,即便是非常小的地方都有点可以挖掘.比如ReLU. ReLU的有效性体现在两个方面: 克服梯度消失的问题 加快训练速度 而这两个方面是相辅相成的,因为克 ...