栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ Primer学习笔记-----第十四章:重载运算与类型转换

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ Primer学习笔记-----第十四章:重载运算与类型转换

这一章重载运算符和类型转换比较简单,直接看书理解就行。
但也比较容易出现错误,仔细看书就行。
重载运算符和类型转换是为了更好的使用类型,即使没有不使用这个技术也不影响。


下面说一下函数调用运算符:()

如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象。
因为这样的类同时也能存储状态,所以与普通函数相比它们更灵活。例如:
struct absInt
{
	int operator()(int val) const		//返回绝对值
	{
		return val<0 ? -val : val;
	}	
};

int i = -3;
absInt obj;
int ui = obj(i); 	//等价于:obj.operator()(i);  就是函数调用

我们可以调用obj,即使obj只是一个对象而非函数。
***调用对象实际上是在运行重载的调用运算符:本例中,该运算符接受一个int值并返回其绝对值。
函数调用运算符必须是成员函数。一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别。

如果类定义了调用运算符,则该类的对象称作函数对象。因为可以调用这种对象,所以说这些对象的行为像函数一样。

含有状态的函数对象类

函数对象类也可以包含其他成员,函数对象类通常含有一些数据成员,这些成员被用于定制调用运算符中的操作。例如:
class PrintString		//打印字符串,并在末尾添加指定字符
{
public:
	PrintString(ostream &o = cout, char c = ' '):os(o),sep(c) {}
	void operator()(const string &s) const {os< vec{ "abc","aoe","qwer" };
for_each(vec.begin(), vec.end(), PrintString(cerr,'n'));
等价于:第三个参数传递一个函数对象,上面是通过构造函数直接构造,下面是先构造,再传给形参
PrintString print(cerr,'n');
for_each(vec.begin(), vec.end(), print);

lambda是函数对象

当我们编写一个lambda后,编译器将该表达式翻译成一个未命名类的未命名对象。
在lambda表达式产生的类中含有一个重载的函数调用运算符:
如上面的例子用lambda重写:
for_each(vec.begin(),vec.end(),[](const string& s){cout<
public:
	void operator()(const string& s) const
	{cout< return a.size() >= size; });
该lambda表达式产生的类将形如:
class SizeComp
{
public:
	SizeComp(size_t n):size(n){}	//对应的捕获的变量
	bool operator()(const string& s) const	//该调用运算符的返回类型、形参和函数体斗鱼lambda一致
	{ return s.size() >= size; }
private:
	size_t size;	//对应的捕获的变量
};

lambda表达式产生的类不含默认构造函数、赋值运算符及默认析构函数;它是否含有默认的拷贝/移动构造函数则通常要视捕获的
数据成员类型而定。

标准库定义的函数对象

在算法中使用标准库函数对象

重点:可调用对象与function

不同类型可能具有相同的调用形式

学过C#的同学知道,委托和这个功能类似。



自己简单实现类似C#委托的功能:比较简陋,只是提供一个思路

class Action
{
	typedef function  Fun;		//函数类型是无返回值,接受一个int参数
public:
	void operator()(int value)				//重载函数调用运算符
	{
		for (auto fun : vec)
		{
			fun(value);
		}
	}

	void operator+=(Fun fun)				//重载+=运算符
	{
		
			vec.push_back(fun);
	}
	
	//这里不注释会报错,
	
private:
	vector vec;
};

void Test(int i)					//一般函数
{
	cout << "Test" << i << endl;
}

struct Test2
{
	void operator()(int i)			//函数对象
	{
		cout << "Test2" << i << endl;
	}
};

void main()
{
	Action myAction;
	myAction += [] (int a) { cout << "lambda" << a << endl; };	//lambda表达式
	myAction += Test;
	myAction += Test2();
	myAction(666);			//利用函数对象执行调用
}

上面会报错的代码的原因:
find会进行==比较两个函数原型void(int),因为没有重载找不到,所以报错。
可以自己重载==操作,但现在还不知道怎么判断两个相同函数原型的函数的相等性

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1030631.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号