摘要:运算符能给程序员提供一种书写数学公式的感觉,本质上运算符也是一种函数,因此有类内部运算符和全局运算符之分,通过重载,运算符的“动作”更加有针对性,编写代码更像写英文文章。

1、C++标准允许将运算符重载为类成员或者全局的,一般如果是全局的话,为了效率,都是把它们定义为类友元函数。

 /*
** 重载全局运算符“+”、“-”,代码如下:
*/
#include <iostream> using namespace std; //class Complex;
//Complex operator+(const Complex &c1, const Complex &c2);
//Complex operator-(const Complex &c1, const Complex &c2);
// 我的疑问:声明为全局的有什么好处的,或者说有什么必要的么?
class Complex
{
public:
Complex(double real = 0.0, double image = 0.0)
{
this->real = real;
this->image = image;
}
public:
void displayComplex()
{
if(image >= )
cout << "(" << real << '+' << image << 'i' << ")";
else
cout << "(" << real << image << 'i' << ")";
}
friend Complex operator+(const Complex &c1, const Complex &c2);
friend Complex operator-(const Complex &c1, const Complex &c2);
private:
double real;
double image;
}; Complex operator+(const Complex &c1, const Complex &c2)
{
Complex complexTemp;
complexTemp.real = c1.real + c2.real;
complexTemp.image = c1.image + c2.image;
return complexTemp;
}
Complex operator-(const Complex &c1, const Complex &c2)
{
Complex complexTemp;
complexTemp.real = c1.real - c2.real;
complexTemp.image = c1.image - c2.image;
return complexTemp;
}
int main()
{
Complex c, c1(1.1, 2.2), c2(3.3, 4.4);
c = c1 + c2;
c = c1 - c2; // operator-(c1, c2);
c1.displayComplex();
cout << "-";
c2.displayComplex();
cout << "=";
c.displayComplex();
cout << endl; int i;
cin >> i;
return ;
}

重载为友元函数

2、运算符重载的一些基本规则:

禁止用户发明C++语言运算符之外的其他运算符

不要试图改变重载运算符的语义,保持重载后的运算语义与内置运算符语义一致,否则会带来思维上的混乱

不能重载.、.*、::、?:

不能重载#、##

不能重载sizeof()、typeid()

不能重载static_cast<>、dynamic_cast<>、const_cast<>、reinterpret_cast<>

3、运算符重载时,它的返回值类型会有程序运行效率和使用重载运算符方便程度的差别

当返回值为对象时,拷贝构造函数会构建一个临时对象

当返回值为对象引用时,不会引起构造函数的调用,其返回值可以作为左值

当返回值为对象指针时,不会引发构造函数的调用,其返回值可以作为左值

 /*
** 重载运算符,返回不同类型的差别
*/
#include <iostream> using namespace std; class Complex
{
public:
Complex(double real = 0.0, double image = 0.0)
{
this->real = real;
this->image = image;
}
Complex(const Complex &c) // 拷贝构造函数
{
real = c.real;
image = c.image;
cout << "copy constructing..." << endl;
}
public:
Complex operator+(const Complex &c)
{
Complex complexTemp;
complexTemp.real = real + c.real;
complexTemp.image = image + c.image;
return complexTemp; // 此时会调用拷贝构造函数,构造一个临时对象
}
Complex& operator-(const Complex &c)
{
real -= c.real;
image -= c.image;
return *this;
}
void displayComplex()
{
if(image >= )
cout << "(" << real << "+" << image << "i" << ")";
else
cout << "(" << real << image << "i" << ")";
}
private:
double real;
double image;
};
int main()
{
Complex c, c1(1.1, 2.2), c2(3.3, 4.4);
(c1 + c2).displayComplex();
cout << "Before c1 - c2" << endl;
c1.displayComplex();
cout << endl;
cout << "After c1 - c2" << endl;
(c1 - c2).displayComplex();
cout << endl;
int i;
cin >> i;
return ;
}

重载返回值不同类型的差别

4、运算符重载示例:

赋值运算符

 /*
** 赋值运算符“=”重载
*/
#include <iostream>
#include <cstring> using namespace std; class Student
{
public:
Student(char *name = "")
{
pName = new char[strlen(name) + ];
strcpy(pName, name);
}
~Student()
{
delete pName;
pName = NULL;
}
public:
Student &operator=(const Student &student)
{
cout << "assignment called..." << endl;
// 若为同一个对象则直接返回即可
if(this == &student) // 注意这里需要用指针比较,因为没有实现对象比较的运算符呢
{
cout<< "\tExact the same object." << endl;
return *this;
}
delete pName; // 否则,先释放资源
pName = new char[strlen(student.pName) + ];
strcpy(pName, student.pName);
return *this;
}
void show()
{
cout << pName << endl;
}
private:
char *pName;
}; int main()
{
Student s1, s2("zhangsan");
s1 = s1; s1 = s2;
s1.show(); int i;
cin >> i;
return ;
}

赋值运算符重载示例

函数符

 /*
** 函数符“()”重载
*/
#include <iostream> using namespace std; class Student
{
public:
Student(int chinese, int math, int english)
{
this->chinese = chinese;
this->math = math;
this->english = english;
}
~Student()
{ }
public:
void operator()(int index = )
{
switch(index)
{
case :
cout << "chinese:" << chinese << endl;
break;
case :
cout << "math:" << math << endl;
break;
case :
cout << "english:" << math << endl;
break;
default:
cout << "not found" << endl;
}
}
private:
int chinese;
int math;
int english;
};
int main()
{
Student student(, , );
student();
student();
student();
student();
student();
student(); int i;
cin >> i;
return ;
}

函数调用符重载示例

下标运算

 /*
** 下表运算符“[]”重载
*/
#include <iostream> using namespace std; class UserString
{
public:
UserString(char *str)
{
len = strlen(str);
this->str = new char[len + ];
strcpy(this->str, str);
}
~UserString()
{
delete str;
str = NULL;
}
public:
char operator[](int index)
{
if(index >= && index < len) // 判断越界
return str[index];
else
{
cout << "beyond scope..." << endl;
return ' ';
}
}
int getLength()
{
return len;
}
private:
char *str;
int len;
}; int main()
{
UserString us("zhangsan");
cout << "\"zhangsan\" length:" << us.getLength() << endl;
int length = us.getLength();
int i;
for(i = ;i < length;i++)
cout << us[i]; // 使用[]访问
cout << endl;
cout << us[i]; cin >> i;
return ;
}

下表运算符重载示例

运算符++、--

 /*
** 运算符“++、--”重载
*/
#include <iostream> using namespace std; class Integer
{
public:
Integer(int data)
{
this->data = data;
}
Integer(const Integer &i)
{
this->data = i.data;
}
~Integer()
{ }
public:
Integer operator++(int)
{
Integer temp(*this);
data++;
return temp;
}
Integer operator++()
{
data++;
return *this;
}
void show()
{
cout << data << endl;
}
private:
int data;
}; int main()
{
Integer x();
(x++).show();
(++x).show(); int i;
cin >> i;
return ;
}

++、--运算符重载示例

类型转换

 /*
** 类型转换运算符重载,从对象到内置类型
*/
#include <iostream> using namespace std; class Complex
{
public:
Complex(double real, double image)
{
this->real = real;
this->image = image;
}
public:
operator double()
{
return real;
}
private:
double real;
double image;
}; int main()
{
double d = 1.1;
Complex c(4.0, 5.0); d += c; // 此时c.operator double()返回4.0
cout << d << endl; int i;
cin >> i;
return ;
}

类型转换-从对象到内置类型

 /*
** 类型转换运算符重载,从内置类型到对象
*/
#include <iostream> using namespace std; class Complex
{
public:
Complex(double real, double image)
{
this->real = real;
this->image = image;
}
Complex(const Complex &c)
{
real = c.real;
image = c.image;
cout << "copy constructor called..." << endl;
}
Complex(double real)
{
this->real = real;
this->image = ;
cout << "one parameter called..." << endl;
}
~Complex()
{}
public:
Complex& operator+=(const Complex &c)
{
real += c.real;
image += c.image;
cout << "overload operator+= called..." << endl;
return *this;
}
void show()
{
cout << real;
if(image >= )
cout << "+" << image << "i" << endl;
else
cout << image << "i" << endl;
}
private:
double real;
double image;
}; int main()
{
Complex c1(, 1.1);
c1 += 3.3;
c1.show(); int i;
cin >> i;
return ;
}

类型转换-从内置类型到对象

5、运算符重载规则

运算符 规则
所有单目运算符 建议重载为非static成员函数
=、()、[]、->、* 建议重载为非static成员函数
+=、-=、/=、*=、&=、|=、~=、%=、>>=、<<= 建议重载为非static成员函数
所有其他运算符 建议重载为全局函数或类的友元函数

C++面向对象程序设计的一些知识点(5)的更多相关文章

  1. C++面向对象程序设计的一些知识点(4)

    摘要:累继承可以实现源代码重用,模板技术也可以达到同样的目的.模板可以分为函数模板和类模板,其共同点是允许参数类进行类型化,编译器根据程序员传递的具体类型,又把函数模板实例化为具体函数,把类模板实例化 ...

  2. C++面向对象程序设计的一些知识点(3)

    摘要:多态性提供一组统一的调用接口函数,依据这些条用接口函数具体对象的不同,同一名字的函数会有不同的行为. 1.重载与隐藏 (1).对同一作用域中的同名函数,如果它们的函数特征标不同,那么它们就形成一 ...

  3. C++面向对象程序设计的一些知识点(2)

    1.C++中三种继承方式及派生类中访问控制规则 (1).C++支持的三种继承方式是public.protected.private.C++允许一个类同时以不同的方式对不同的基类加以继承. (2). 不 ...

  4. C++面向对象程序设计的一些知识点(1)

    1.函数重载而不出错是有条件的: (1).这些函数位于同一域内,如同一类中.同一文件中. (2).这些同名函数具有不同的参数特征标(特征标是指形參的个数.类型.排列顺序等). 2.引用特性(与指针对比 ...

  5. 对面向对象程序设计(OOP)的认识

    前言 本文主要介绍面向对象(OO)程序设计,以维基百科的解释: 面向对象程序设计(英语:Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发 ...

  6. 20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计

    20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ...

  7. 2018-2019-2 20175217 实验二《Java面向对象程序设计》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吴一凡 学号:20175217 指导教师:娄嘉鹏 实验日期:2019年4月15日 实验时间:--- 实验序号:实验二 实验名称:Jav ...

  8. 20175315 实验二《Java面向对象程序设计》实验报告

    20175315 实验二<Java面向对象程序设计>实验报告 一.实验内容及步骤 1.初步掌握单元测试和TDD 单元测试 任务一:三种代码 用程序解决问题时,要学会写以下三种代码: 伪代码 ...

  9. 2018-2019-2 20175202实验二《Java面向对象程序设计》实验报告

    2018-2019-2 20175202实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ...

随机推荐

  1. js 垃圾回收机制与内存管理

    1.原理 js按照固定的时间间隔找到不在继续使用的变量,释放其占用的内存. 2.实现方式 (1)标记清除 垃圾收集器给存储在内存上的所有变量都加上标记: 之后,去掉环境中的变量以及被环境引用变量的标记 ...

  2. TestNG方法測试及注意要点 代码及配置具体解释(解决testng方法不运行问题)

    教你解决为什么TestNG中方法加了@Test注解,也在配置文件里配置了,可是方法就是不运行! 在使用TestNG进行測试时,使用配置文件的方式更easy于维护.可是常常遇到明明方法写了也配置运行了, ...

  3. 在阿里云上进行Docker集群的自动弹性伸缩

    摘要: 在刚刚结束的云栖大会上,阿里云容器服务演示了容器的自动弹性伸缩,能够从容应对互联网应用的峰值流量.阿里云容器服务不仅支持容器级别的自动弹性伸缩,也支持集群节点级别的自动弹性伸缩.从而真正做到从 ...

  4. http1.1 协议响应方面参数

    HTTP1.1   提供了一个必须的Host字段,而且建立好一次连接之后可以重复使用.提高用户的上网体验. 响应信息 HTTP/1.1 200 OK                           ...

  5. 【LeetCode】40. Combination Sum II (2 solutions)

    Combination Sum II Given a collection of candidate numbers (C) and a target number (T), find all uni ...

  6. 基于node.js的web框架express

    1.安装node.js方法: window :https://nodejs.org/en/ linux:http://www.runoob.com/nodejs/nodejs-install-setu ...

  7. 百度UEditor富文本编辑器去除过滤div等标签

    将设计排版好的页面html代码上传到数据库,再读取出来的时候发现所有的div都被替换成了p标签. 解决方法: 首先在ueditor.all.js文件内搜索allowDivTransToP,找到如下的代 ...

  8. if语句的数据驱动优化(Java版)

    举个栗子,如果我要输出数字对应的中文描述,我可以用这种方法来写: int num=2; if (num==1){ System.out.println("一"); } else i ...

  9. Jquery与mootools对比

    换了新公司以后就很少使用原生Js来实现界面交互了,而是更多的依赖Jquery. 1.Jquery优点: 良好的一致性$().().xxxxx与强大的DOM api组件可以让一个js菜鸟一周之类立马开发 ...

  10. Ext.net中Combobox如何绑定数据库中的值-通用方法

    今天在项目中再次碰到了问题,就是Combobox中的值如果是直接绑定很简单.简单添加项就行了.代码如下: <ext:ComboBox ID=" /> </Items> ...