8.4 C++ 运算符重载
C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
实现函数重载: 函数重载是C++语言区别于C语言的重要特性,重载就是定义名称相同但符号或后面参数不同的函数,当重载时,编译器会偷偷在相同函数名的前面加上_func关键字字段,以此来实现重载后函数名不重复,通过编译检查.
#include <iostream>
using namespace std;
int func(int x) { return x; }
int func(int x, int y) { return x + y; }
double func(double x, double y) { return x + y; }
int main(int argc, char *argv[])
{
int ret1 = func(10);
int ret2 = func(100, 200);
double ret3 = func(10.5, 20.4);
cout << ret1 << ret2 << ret3 << endl;
system("pause");
return 0;
}
重载与仿函数: 仿函数就是伪函数,一般情况下仿函数需要配合()重载小括号,来实现类似函数调用一样的语法.
#include <iostream>
#include <string>
using namespace std;
class MyPrint
{
public: void operator()(string text)
{
cout << text << endl;
}
};
class MyAdd
{
public: int operator()(int x, int y)
{
return x + y;
}
};
int main(int argc, char *argv[])
{
MyPrint print;
print("hello lyshark"); // 使用仿函数
cout << MyAdd()(100, 200) << endl; // 匿名仿函数
system("pause");
return 0;
}
重载加号运算符: 重载加号运算符,类p3 = p1 + p2重载后等于p3.m_x = p1.m_x + p2.m_x两个数据成员相加.
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int m_x;
int m_y;
public:
Person(){};
Person(int x, int y) :m_x(x), m_y(y) {}
// 加号运算符重载,这里其实是二元,因为隐藏了一个this指针.
Person operator + (Person &p)
{
Person tmp;
tmp.m_x = this->m_x + p.m_x;
tmp.m_y = this->m_y + p.m_y;
return tmp;
}
};
int main(int argc, char *argv[])
{
Person p1(10, 40);
Person p2(20, 90);
// 此处相当于 p1(10) + p2(20) / p1(40) + p2(90)
Person p3 = p1 + p2;
cout << "p3 m_x = > " << p3.m_x << endl;
cout << "p3 m_y = > " << p3.m_y << endl;
system("pause");
return 0;
}
重载全局函数: 重载运算符可以定义在一个类的内部,也可以定义在类外,定义在类外的则属于全局重载函数.
#include <iostream>
using namespace std;
class Person
{
public:
int m_x;
int m_y;
public:
Person(){};
Person(int x, int y) :m_x(x), m_y(y) {}
};
// 全局函数实现运算符重载,这个就属于二元运算符重载
Person operator +(Person &p1, Person &p2)
{
Person tmp;
tmp.m_x = p1.m_x + p2.m_x;
tmp.m_y = p1.m_y + p2.m_y;
return tmp;
}
int main(int argc, char *argv[])
{
Person p1(10, 30);
Person p2(20, 50);
Person p3 = p1 + p2;
cout << "p3 m_x = > " << p3.m_x << endl;
cout << "p3 m_y = > " << p3.m_y << endl;
system("pause");
return 0;
}
重载左移运算符: 使用<<重载左移运算符,让cout直接输出两个变量,重载左移运算符不可以写成成员函数.
#include <iostream>
#include <string>
using namespace std;
class Person
{
friend ostream& operator<<(ostream &cout, Person &ptr);
private:
int m_x;
int m_y;
public:
Person(){};
Person(int x, int y) :m_x(x), m_y(y) {}
};
ostream& operator << (ostream &cout, Person &ptr)
{
cout << "m_x = " << ptr.m_x << " ----> " << "m_y = " << ptr.m_y << endl;
return cout;
}
int main(int argc, char *argv[])
{
Person p1(10, 30);
Person p2(20, 10);
cout << p1 << endl;
cout << p2 << endl;
system("pause");
return 0;
}
重载自增/自减运算符: 自增运算符有两种形式第一种是前置自增运算符,这一种需要定义为MyInteger& operator ++ (),而后自增运算符则需要增加一个int占位符MyInteger operator ++ (int)这样编译器才会分得出来是重载前还是后.
#include <iostream>
#include <string>
using namespace std;
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger & myInt);
public:
int m_count;
public:
MyInteger() { m_count = 0; }
// 重载前置 ++x 运算符
MyInteger& operator ++ ()
{
this->m_count++;
return *this;
}
// 重载后置 x++ 运算符,为了区分前后置,需要在参数后面增加一个int占位符
// 此时编译器才会认为我们需要使用后置重载运算符了
MyInteger operator ++ (int)
{
MyInteger tmp = *this;
m_count++;
return tmp;
}
};
ostream& operator<<(ostream& cout, MyInteger & myInt)
{
cout << myInt.m_count;
return cout;
}
int main(int argc, char *argv[])
{
MyInteger myInt;
cout << ++myInt << endl;
cout << myInt++ << endl;
cout << ++(++myInt) << endl;
system("pause");
return 0;
}
重载指针运算符(智能指针): 智能指正用来托管自定义的对象,让对象可以自动的释放数据,当我们使用一个对象结束以后,无需手动释放堆空间,智能指针会帮助我们完成这个过程.
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
char *m_name;
int m_age;
public:
Student(char *name, int age)
{
this->m_name = name;
this->m_age = age;
}
void Print()
{
cout << "Name: " << this->m_name << endl;
cout << "Age: " << this->m_age << endl;
}
};
// 定义智能指针,用于自动释放对象所占用的空间
class Smart_Pointer
{
private:
Student *ptr;
public:
// 先来执行构造函数,将传入的指针复制到内部
Smart_Pointer(Student *ptr)
{ this->ptr = ptr; }
// 重载运算符 -> 让智能指针能够直接指向Student
Student * operator -> ()
{ return this->ptr; }
// 重载运算符 *
Student & operator * ()
{ return *this->ptr; }
// 定义析构函数,这是智能指针的关键部分,对象会被自动释放
~Smart_Pointer()
{
if (this->ptr != NULL)
{
delete this->ptr;
this->ptr = NULL;
}
}
};
int main(int argc, char *argv[])
{
// 手动释放的案例:平常的使用方式
Student *stu = new Student("lyshark", 10);
stu->Print();
delete stu;
// 使用智能指针:则无需考虑释放的问题
Smart_Pointer ptr(new Student("lyshark", 10));
ptr->Print();
(*ptr).Print();
system("pause");
return 0;
}
重载赋值运算符: 我们将等于号进行重载,实现对类中数据成员的赋值拷贝.
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
int m_uid;
char *m_name;
public:
Student(int uid, char *name)
{
this->m_uid = uid;
this->m_name = new char[strlen(name) + 1];
strcpy(this->m_name, name);
}
// 重载 = 实现类数据成员的赋值运算
Student& operator = (const Student &ptr)
{
// 先来判断原来的堆区是否有内容,如果有则先来释放
if (this->m_name != NULL)
{
this->m_uid = 0;
delete[] this->m_name;
this->m_name = NULL;
}
// 否则,我们直接开辟空间完成内存拷贝
this->m_name = new char[strlen(ptr.m_name) + 1];
strcpy(this->m_name, ptr.m_name);
this->m_uid = ptr.m_uid;
return *this;
}
// 析构函数,则需要释放内存
~Student()
{
if (this->m_name != NULL)
{
this->m_uid = 0;
delete[] this->m_name;
this->m_name = NULL;
}
}
};
int main(int argc, char *argv[])
{
Student stu1(1,"lyshark");
Student stu2(2, "admin");
Student stu3(0, "");
stu3 = stu2 = stu1;
cout << stu3.m_name << endl;
cout << stu2.m_name << endl;
cout << stu1.m_name << endl;
system("pause");
return 0;
}
重载关系运算符: 重载关系运算符则可以实现两个类对象的直接对比.
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
int m_uid;
char * m_name;
public:
Student(int uid,char *name)
{
this->m_uid = uid;
this->m_name = name;
}
bool operator == (Student &ptr)
{
if (this->m_uid == ptr.m_uid && this->m_name == ptr.m_name)
return true;
return false;
}
bool operator != (Student &ptr)
{
if (this->m_uid != ptr.m_uid && this->m_name != ptr.m_name)
return true;
return false;
}
};
int main(int argc, char *argv[])
{
Student stu1(1, "lyshark");
Student stu2(1, "lyshark");
Student stu3(2, "admin");
if (stu1 == stu2)
cout << "stu1 = stu2" << endl;
if (stu1 != stu3)
cout << "stu1 != stu3" << endl;
system("pause");
return 0;
}
8.4 C++ 运算符重载的更多相关文章
- C++ 运算符重载时,将运算符两边对象交换问题.
在C++进行运算符重载时, 一般来讲,运算符两边的对象的顺序是不能交换的. 比如下面的例子: #include <iostream> using namespace std; class ...
- C#高级编程笔记2016年10月12日 运算符重载
1.运算符重载:运算符重重载的关键是在对象上不能总是只调用方法或属性,有时还需要做一些其他工作,例如,对数值进行相加.相乘或逻辑操作等.例如,语句if(a==b).对于类,这个语句在默认状态下会比较引 ...
- C++运算符重载
C++运算符重载 基本知识 重载的运算符是具有特殊名字的函数,他们的名字由关键字operator和其后要定义的运算符号共同组成. 运算符可以重载为成员函数和非成员函数.当一个重载的运算符是成员函数时, ...
- 标准C++之运算符重载和虚表指针
1 -> *运算符重载 //autoptr.cpp #include<iostream> #include<string> using namespace std ...
- python运算符重载
python运算符重载就是在解释器使用对象内置操作前,拦截该操作,使用自己写的重载方法. 重载方法:__init__为构造函数,__sub__为减法表达式 class Number: def __in ...
- PoEduo - C++阶段班【Po学校】-Lesson03-5_运算符重载- 第7天
PoEduo - Lesson03-5_运算符重载- 第7天 复习前面的知识点 空类会自动生成哪些默认函数 6个默认函数 1 构造 2 析构 3 赋值 4 拷贝构造 5 oper ...
- 不可或缺 Windows Native (24) - C++: 运算符重载, 自定义类型转换
[源码下载] 不可或缺 Windows Native (24) - C++: 运算符重载, 自定义类型转换 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 运算符重载 自 ...
- 我的c++学习(8)运算符重载和友元
运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能.这个函数叫做运算符重载函数(常为类的成员函数). 方法与解释 ◆ 1.定义运 ...
- c/c++面试题(6)运算符重载详解
1.操作符函数: 在特定条件下,编译器有能力把一个由操作数和操作符共同组成的表达式,解释为对 一个全局或成员函数的调用,该全局或成员函数被称为操作符函数.该全局或成员函数 被称为操作符函数.通过定义操 ...
- 实验12:Problem H: 整型数组运算符重载
Home Web Board ProblemSet Standing Status Statistics Problem H: 整型数组运算符重载 Problem H: 整型数组运算符重载 Tim ...
随机推荐
- Lambda 表达式各种用法,你都会了吗
公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 前言 Lambda表达式是 Java 8 中引入的最有影响力的功能之一.它们通过允许简洁而优雅地创建匿名函数来实现 Jav ...
- Windows下的Linux子系统(WSL)
什么是WSLWSL:Windows subsystem for Linux,是用于Windows上的Linux的子系统作用很简单,可以在Windows系统中获取Linux系统环境,并完全直连计算机硬件 ...
- js将页面上取得的元素坐标转换为电脑屏幕坐标
代码: <!DOCTYPE html> <html> <head> <title>计算屏幕坐标</title> <meta chars ...
- .net 温故知新【17】:Asp.Net Core WebAPI 中间件
一.前言 到这篇文章为止,关于.NET "温故知新"系列的基础知识就完结了,从这一系列的系统回顾和再学习,对于.NET core.ASP.NET CORE又有了一个新的认识. 不光 ...
- C#开源跨平台的多功能Steam工具箱&GitHub加速神器
前言 作为一个程序员你是否会经常会遇到GitHub无法访问(如下无法访问图片),或者是访问和下载源码时十分缓慢就像乌龟爬行一般.今天分享一款C#开源的.跨平台的多功能Steam工具箱和GitHub加速 ...
- python之HtmlTestRunner(一)生成测试报告
一.下载安装 windows10,cmd环境通过如下命令
- java基础-方法method-day05
1. 语法 [修饰符] 返回值类型 方法名(形参列表){ 逻辑主体 } public class TestMethod01{ public static int add(int num1, int n ...
- 每天学五分钟 Liunx 011 | sudo
回顾前两节,在 001 中介绍了怎么添加用户及用户组,在 010 中介绍了从 client 端 ssh 到 server 的详细过程,那么接下来要介绍的就是是登陆到 server 之后如何切换用户了. ...
- 13个构建RESTful API的最佳实践
前言 Facebook.GitHub.Google和其他许多巨头都需要一种方法来服务和消费数据.在今天的开发环境中,RESTful API仍然是服务和消费数据的最佳选择之一. 但你是否考虑过学习行业标 ...
- 【ARM】为堆和栈保留空的内存块
此示例演示如何使用分散加载描述为堆栈和堆保留和清空内存块.它还显示链接器生成的相关符号. 在以下示例中,执行区域定义STACK 0x800000 EMPTY -0x10000定义了一个名为STACK ...