C++第十四章运算符重载应用案例

news/2024/9/22 22:26:13/

1)//函数对象包装器:就是相当于把函数也封装成容器使用;
//支持4种函数的封装:普通函数,成员函数,匿名函数,仿函数

#include <iostream>
#include <string>
#include <map> 
#include <functional> 
int test(int n) //普通函数
{std::cout<<"n is:"<<n<<std::endl;return 4;
}
class People
{
public:People(){}int MyPeople(int n) //成员函数{std::cout<<"people is:"<<n<<std::endl;return 0;}
};class Sort
{
public:int operator()(int n){std::cout<<"sort is:"<<n<<std::endl;        return 0;}
};int main()
{std::function<int(int)> f1 = test;f1(3);std::function<int(People*,int)> f2 = &People::MyPeople;People p1;f2(&p1,33);std::function<int(Sort*,int)> f3 = &Sort::operator();Sort s1;f3(&s1,444);std::function<int(int)> f4 = [](int n)->int{ std::cout<<"lambda number is:"<<n<<std::endl;        return 0;};f4(5);return 0;
}
  1. 移动构造函数,注意右值的使用,代码如下:
#include <iostream>
#include <string>
#include <map> 
#include <functional> 
#include <vector>
using namespace std;class Move
{
public:int a_;Move(int a) : a_(a){cout<<"in constructor"<<a<<endl;}Move(const Move& move){cout<<"copy constructor"<<move.a_<<endl;}// move constructorMove(Move&& move) noexcept //不要抛异常{cout<<"in move constructor"<<move.a_<<endl;this->a_ = move.a_;}~Move(){cout<<"in destructor"<<endl;}
};int main(void)
{vector<Move>   vec;vec.push_back(Move{10});return 0;
}

3)顶层const和底层const的函数重载
//把鼠标放到func函数上,会提示void func(int* a)
void func(int* const a){ } //与下面是统一函数(const 可以去掉),所以重载失败
void func(int* a) {}
4)类内重载加号+运算符和类外重载加号+运算符的案例1:

#include <iostream>
using namespace std;class A
{
public:A(int a) : a_(a){}A(void) : a_(0){}//默认构造friend A operator+(const A& lhs,const A& rhs); //不用声明也可以编译通过A& operator+(const A& a){cout<<"in operator+"<<a.a_<<endl;this->a_ += a.a_;return *this;}int a_;
};A operator+(const A& lhs,const A& rhs)
{A a;cout<<"gengral operator+"<<endl;a.a_ = lhs.a_ + rhs.a_;return a;
}int main(void)
{A a1(1);A a2(2);                A a3 = a1 + a2; //binary operand 二元运算,优先选择类内的运算符重载,如果没有,则到类外找(name lookup)cout<<"a1: "<<a1.a_<<endl;  cout<<"a2: "<<a2.a_<<endl;    cout<<"a3: "<<a3.a_<<endl;    return 0;
}

5)运算符operator<<函数的使用(输出运算符重载)

#include <iostream>
#include<ostream>
using namespace std;class A
{
public:int num;A(int a) : num(a){}friend ostream& operator<<(ostream &out,const A& a); //这个friend必须得写
};ostream& operator<<(ostream &out,const A& a)
{out<<"in operator<<: "<<a.num<<endl;return out;
}int main(void)
{A a1(3);cout<<a1<<endl;return 0;
}

6)关系运算符重载operator==,operator!=的使用案例:

#include <iostream>
#include<map>using namespace std;class A
{
public:A(int a) : a_(a){}bool operator==(const A& a2){ cout<<"in operator== "<<endl; return this->a_ == a2.a_; }bool operator!=(const A& a2){ cout<<"in operator!= "<<endl; return !(*this == a2); } //把工作交给另外一个成员函数去做 int a_;
};int main(void)
{A a1(1);A a2(1);cout<<(a1 != a2)<<endl;return 0;
}//输出结果:
in operator!= 
in operator== 
0

7)赋值运算符重载案例:(赋值运算符必须是成员函数):

#include <iostream>
#include<initializer_list>
#include<vector>using namespace std;class A
{
public:vector<int> vec;A& operator=(std::initializer_list<int> list){for(const int& num : list)   {vec.push_back(num);}return *this;}
};int main(void)
{A a;a = {1,2,3,4};cout<<a.vec.back()<<endl;return 0;
}

8)下标运算符重载案例:

#include <iostream>
#include<initializer_list>
#include<vector>using namespace std;class A
{
public:vector<int> vec = {2,3};A& operator=(std::initializer_list<int> list){for(const int& e: list){vec.push_back(e);}return *this;}int& operator[](std::size_t index) //operator[]下标运算符重载{cout<<"in operator[] "<<endl;return vec[index];}//const主要用于带有const对象案例const int& operator[](std::size_t index) const //如果定义了非const的,则也需要定义const的{cout<<"in const operator[]"<<endl;return vec[index];}
};
int main(void)
{A a1;a1 = {1,2,3};cout<<a1[0]<<endl;const A a2; cout<<a2.operator[](0)<<endl;cout<<a2[0]<<endl;return 0;
}

9)前置++和后置++的运算符重载:

#include <iostream>
#include<initializer_list>
#include<vector>using namespace std;class Point
{
public:int x_;int y_;Point(int x,int y) : x_(x),y_(y){}Point& operator++(void) //前置++{cout<<"prefix++"<<endl;this->x_++;this->y_++;return *this;}const Point operator++(int) //后置++{cout<<"postfix++"<<endl;Point tmp = *this;this->x_++;this->y_++;return tmp;}    friend ostream& operator<<(ostream& out,const Point& p);
};ostream& operator<<(ostream& out,const Point& p)
{out<<"x:"<<p.x_<<" "<<"y:"<<p.y_<<endl;return out;
}
int main(void)
{Point p(2,2);cout<<++p<<endl;    //输出3 3cout<<p++<<endl;    //输出3 3后point变为4 4cout<<p<<endl;      //输出4 4return 0;
}

10)-> arrow 运算符重载案例:(arrow ->: overload member access)案例:

#include <iostream>
#include<initializer_list>
#include<vector>using namespace std;class A
{
public:int* a_;A(int a) : a_(new int(a)){}~A(){delete a_;}void func(void){cout<<"class A func running"<<endl;}
};class Point
{
public:int x_;int y_;A* pa_;Point(int x,int y) : x_(x),y_(y),pa_(new A(x)){}A* operator->(void)  //一定要返回指针{cout<<"in point"<<endl;return pa_;}
};
//通过->运算符重载,point可以触及到本不属于自己类的成员!!!
int main(void)
{Point point(2,2);point->func(); //等价于 point.operator->()->func();int* res = point->a_;cout<<"res: "<<(*res)<<endl;return 0;
}
  1. 重载小括号()运算符(函数对象)和lambda的案例:
#include <iostream>
#include<initializer_list>
#include<vector>using namespace std;class A
{
public:int a_;A(int a) : a_(a){}A& operator()(int a){this->a_ += a;return *this;}
};
//函数对象和lambda其实本质上是一样的!
int main(void)
{A a(4);a(5);cout<<a.a_<<endl; //输出9;auto ret = [](){ //一般都用auto接匿名函数return 2 + 2;};cout<<"ret: "<<ret()<<endl; //输出4return 0;
}

http://www.ppmy.cn/news/348034.html

相关文章

【哈佛积极心理学笔记】第2讲 为什么要学习积极心理学

第2讲 为什么要学习积极心理学 The first reason is that it is important to focus on what works. Because what works or what we focus on rather creates reality. Second reason is that being happy is not just the negation of the unhappiness. It doesn’t mean t…

软考A计划-2023系统架构师-知识点集锦(2/4)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

Springboot整合Elasticsearch(一):Linux下安装 Elasticsearch 8.x

1、下载安装包&#xff0c;官方下载地址&#xff1a; Past Releases of Elastic Stack Software | Elastic elasticsearch-8.8.1-linux-x86_64.tar.gz 2、拷贝到 Linux 服务器上&#xff0c; 执行解压缩命令 安装包路径&#xff1a;/home/ELK_8.8.1 [rootlocalhost ELK_8.8.1]…

android 炫酷3d主页,五款超酷安卓手机3D桌面软件合辑推荐

3D桌面一直以来都是备受大家青睐的东西&#xff0c;没办法&#xff0c;3D桌面主题既绚丽又实用&#xff0c;没人会不喜欢。3D桌面给人们展示的是一个不同维度的世界&#xff0c;人们会感觉更立体、更逼真&#xff0c;色彩效果也会更加灿烂&#xff0c;给我们以非常好的视觉享受…

【笔记】Android WallpaperService实现视频壁纸、相机桌面

这几天对前段事件比较火的视频壁纸产生了兴趣&#xff0c;也已经有了很多的实现&#xff0c;这里自己做下记录&#xff0c;也尝试着实现了一下相机壁纸&#xff0c;好玩是好玩就是有点费电。 为了兼容6.0之后的权限请求&#xff0c;可以看下之前写的Android6.0之后权限请求工具…

Android安卓手机3389远程连接电脑桌面教程

前一期我们介绍过安卓手机通过VNC服务远程连接XP/linux桌面的方法&#xff0c;实现起来需要安装VNC服务软件&#xff0c;今天就介绍利用安卓手机来远程连接Windows自带的3389远程桌面&#xff0c;当然手机端也必须安装一个客户端&#xff0c;电脑端使用自带的远程桌面功能 手机…

安卓手机部署分割模型

模型来自&#xff1a;https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.6/contrib/PP-HumanSeg/README_cn.md中的 PP-HumanSegV2-Lite。部署到手机上用的是MNN。安卓手机。 本文工程地址 先看结果 高亮的就是分割的人像结果 流程 若要自己转模型&#xff0c;请…

android分辨率选择,安卓Android手机屏幕壁纸分辨率选择技巧

大家先看看对应的壁纸分辨率: 屏幕分辨率为 480320 的Android手机,对应的壁纸分辨率为:640x480。 屏幕分辨率为 800480 的Android手机,对应的壁纸分辨率为:960x800。 屏幕分辨率为 960540 的Android手机,对应的壁纸分辨率为:1080x960。 一、Android手机壁纸的分辨率 不等…