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

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. window下rabbitmq的配置问题

    最近项目想用个MQ来做业务分离,看了市面上众多产品,最后选了rabbitmq,理由很简单,对window的支持很到位(其实是公司的系列产品都是.net的). 安装方法什么的就不说了,直接到官网下载双击 ...

  2. JS禁止后退键(backspace)使浏览器后退

    背景说明: 今天项目测试中,同事发现一个Bug,当键盘敲下后退键(Backspace)后,浏览器自动后退,不符合需求,故建议禁止浏览器后退键. 提出需求: 当键盘敲下后退键(Backspace)后 1 ...

  3. MONyog_5.6.9.0 key激活|监控MYSQL

    SQLyog与MONyog是一家公司对mysql推出的商业化软件,可能大家对SQLyog很熟悉,MONyog是对mysql-server服务的监控. 脚本执行时长.安全性.等的监控! key:a668 ...

  4. 流动的推荐系统——兴趣Feed技术架构与实现

    流动的推荐系统 我们经常谈论的推荐系统(Recommender System),从形式上看是比较“静态”的推荐,通常位于网页主要信息的周边,比如电商网站的“看了又看”.“买了又买”.这种推荐系统在大多 ...

  5. SDK Build Tools revision (19.0.3) is too low for project Minimum required is 19.1.0

    假设你正在使用Android Studio工具进行开发,且将版本号更新到0.6.0的时候.莫名的出现这种错误 SDK Build Tools revision (19.0.3) is too low ...

  6. PHP中的密码加密的解决方案

    层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家“暴库”,全部遭殃 一般的解决方案 1.将明文密码做单向hash $password = md5($_POST[ ...

  7. poj-----Ultra-QuickSort(离散化+树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 38258   Accepted: 13784 ...

  8. 配置tomcat全局c3p0连接池

    由于项目中多个应用访问同一个数据库,并部署在同一个tomcat下面,所以没必要每个应用都配置连接池信息,这样可能导致数据库的资源分布不均,所以这种情况完全可以配置一个tomcat的全局连接池,所涉及应 ...

  9. 自动化测试尝试 动态Linq表达式生成 ftp上传

    自动化测试尝试   1. Selenium IDE Selenium IDE is a Chrome and Firefox plugin which records and plays back u ...

  10. IIS7的应用程序池详细解析

    在 IIS 7 中,应用程序池有两种运行模式:集成模式和经典模式.应用程序池模式会影响服务器处理托管代码请求的方式 在IIS 7中,添加一个应用程序或者单独的网站,默认会自动新建一个对应的“应用程序池 ...