21、C++ Primer 4th 笔记,重载运算符(2)

简介: 1、自增操作符和自减操作符 为了与内置类型一致,前缀操作符应返回被增量或减量对象的引用;后辍式操作符应返回旧值(不是引用)。后辍式操作符函数接受一个额外的(即无用的)int型形参。 示例 #include "iostream" #include "stdio.

1、自增操作符和自减操作符

为了与内置类型一致,前缀操作符应返回被增量或减量对象的引用;后辍式操作符应返回旧值(不是引用)。后辍式操作符函数接受一个额外的(即无用的)int型形参。

示例

#include "iostream"
#include "stdio.h"
using namespace std;

class CheckedPtr
{
public:
	CheckedPtr(int *b, int *e):beg(b), end(e), curr(e){}
public:
	CheckedPtr& operator++();  //前辍
	CheckedPtr& operator--();
	CheckedPtr  operator++(int);//后辍
	CheckedPtr  operator--(int);
private:
	int *beg;
	int *end;
	int *curr;
};

CheckedPtr& CheckedPtr::operator++()
{
	if (curr == end)
		throw out_of_range("increment past the end of CheckedPtr");
	++curr;
	return *this;
}
CheckedPtr& CheckedPtr::operator--()
{
	if (curr == beg)
		throw out_of_range("decrement past the beginning of CheckedPtr");
	--curr;
	return *this;
}

CheckedPtr CheckedPtr::operator++(int)
{
	CheckedPtr ret(*this);
	++*this; //调用前辍增量操作符,在本函数中无需作越界检查
	return ret;
}
CheckedPtr CheckedPtr::operator--(int)
{
	CheckedPtr ret(*this);
	--*this; //调用前辍减量操作符,在本函数中无需作越界检查
	return ret;
}
int main()
{
	CheckedPtr parr(ia, ia + size);
	parr.operator++(0); //显式调用后辍增量操作符
	parr.operator++();  //显式调用前辍增量操作符
	return 0;
}

显式调用操作符

示例如上中。

所传递的值通常会被忽略,便是必要的。

2、函数调用操作符和函数对象

可以为类类型的对象重载函数调用操作符。一般表示操作的类重载调用操作符。函数调用操作符必须声明为成员函数,可以重载(由形参的数目或类别加以区别)。

示例

#include "iostream"
#include "stdio.h"
using namespace std;

struct absInt
{
	int operator()(int val)
	{
		return val < 0 ? -val:val;
	}
};

int main()
{
	int i = -42;
	absInt absOjb;
	unsigned int ui = absOjb(i);
	return 0;
}

通过为类类型的对象提供一个实参表而使用调用操作符,看起来像一个函数调用。定义了函数调用操作符的类,其对象常称为函数对象,即他们是行为类似函数的对象。

3、将函数对象用于标准库算法

使用谓词函数示例

#include "iostream"
#include "stdio.h"
using namespace std;

bool GT6(const string &s)
{
	return s.size() >= 6;
}

int main()
{
	vector<string>::size_type wc = count_if(words.begin(), words.end(), GT6)
	return 0;
}

使用函数对象比使用谓词函数更灵活。

函数对象示例

#include "iostream"
#include "stdio.h"
#include "algorithm"
#include "functional"
using namespace std;

class GT_cls
{
public:
	GT_cls(size_t val = 0):bound(val){}
	bool operator()(const string &s)
	{
		return s.size() >= bound;
	}
private:
	std::string::size_type bound;
};

int main()
{
	vector<string> words;
	vector<string>::size_type wc = count_if(words.begin(), words.end(), GT_cls(6));
	return 0;
}

4、标准库定义的函数对象

这些标准库函数对象类型放在functional头文件中定义。

算术函数对象类型

函数对象

所应用的操作符

plus<Type>

applies +

minus<Type>

applies -

multiplies<Type>

applies *

divides<Type>

applies /

modulus<Type>

applies %

negate<Type>

applies -

关系函数对象类型

equal_to<Type>

applies ==

not_equal_to<Type>

applies !=

greater<Type>

applies >

greater_equal<Type>

applies >=

less<Type>

applies <

less_equal<Type>

applies <=

逻辑函数对象类型

logical_and<Type>

applies &&

logical_or<Type>

applies |

logical_not<Type>

applies !

    有两个一元函数对象类:一元减(negate<Type>))和逻辑非(logical_not<Type>))。其余的标准库函数对象都是表示二元操作符的二元函数对象类。为二元操作符定义的函数调用操作符需要两个给定类型的形参,而一元函数对象类型定义了接受一个实参的调用操作符。

示例

#include "iostream"
#include "vector"
#include "algorithm"
#include "string"
#include "functional"
using namespace std;

class GT_cls
{
public:
	GT_cls(size_t val = 0):bound(val){}
	bool operator()(const string &s)
	{
		return s.size() >= bound;
	}
private:
	std::string::size_type bound;
};

int main()
{
	plus<int> intAdd;
	int sum = intAdd(10, 20);
	vector<string> svec;
	sort(svec.begin(), svec.end(), greater<string>() );
	cout << sum;
}

5、函数对象的函数适配器

    标准库提供了一组函数适配器,用于特化和扩展一元和二元函数对象。函数适配器分为如下两类:

1)绑定器,是一种函数适配器,它通过将一个操作数绑定到给定值而将二元函数对象转换为一元函数对象。

2)求反器,是一种函数适配器,它将谓词函数对象的真值求反

标准库定义了两个绑定器适配器:bind1st bind2nd。每个绑定器接受一个函数对象和一个值。bind1st 将给定值绑定到二元函数对象的第一个实参,bind2nd 将给定值绑定到二元函数对象的第二个实参。

标准库还定义了两个求反器:not1 not2not1 将一元函数对象的真值求反,not2 将二元函数对象的真值求反。

示例

count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10));
count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 10)));

#include "iostream" 

#include "stdio.h" 

using namespace std;

struct absInt

{

int operator()(int val)

{

return val < 0 ? -val:val;

}

};

int main()

{

int i = -42;

absInt absOjb;

unsigned int ui = absOjb(i);

return 0;

}

目录
相关文章
|
3月前
|
C++
【C++基础】运算符详解
这篇文章详细解释了C++中运算符的用法,包括算术运算符、赋值运算符、比较运算符和逻辑运算符,以及它们在表达式中的作用和示例。
30 2
|
3月前
|
C++
C++(十九)new/delete 重载
本文介绍了C++中`operator new/delete`重载的使用方法,并通过示例代码展示了如何自定义内存分配与释放的行为。重载`new`和`delete`可以实现内存的精细控制,而`new[]`和`delete[]`则用于处理数组的内存管理。不当使用可能导致内存泄漏或错误释放。
|
4月前
|
C++
c++学习笔记02 运算符
C++学习笔记,介绍了C++中的运算符,包括基本的加减乘除、求模、前后置递增递减、赋值运算符、比较运算符和逻辑运算符的使用及其注意事项。
41 6
|
4月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
27 1
|
4月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
68 0
|
5月前
|
NoSQL 编译器 Redis
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
|
5月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
182 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
5月前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
5月前
|
NoSQL Redis C++
c++开发redis module问题之避免多个C++模块之间因重载operator new而产生的冲突,如何解决
c++开发redis module问题之避免多个C++模块之间因重载operator new而产生的冲突,如何解决