C++11中bind绑定器和function函数对象介绍

目录
  • 一. bind1st和bind2nd
    • 1.C++ STL中的绑定器
    • 2.bind1st和bind2nd的底层原理实现
  • 二. 模板的完全特例化和非完全特例化
  • 三. function函数对象
  • 四. bind和function实现线程池
  • 五. lambda表达式
    • 1.lambda表达式的实现原理
    • 2.lambda表达式的应用实践

一. bind1st和bind2nd

1.C++ STL中的绑定器

  • bind1st:operator()的第一个形参变量绑定成一个确定的值
  • bind2nd:operator()的第二个形参变量绑定成一个确定的值

C++11从Boost库中引入了bind绑定器和function函数对象机制

bind可用于给多元函数降元:Bind + 二元函数对象 = 一元函数对象

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>//泛型算法
#include<ctime>
using namespace std;
template<typename Container>
void showContainer(Container& con)
{
	//typename Container::iterator it=con.begin();
	auto it = con.begin();
	for (; it != con.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int> vec;
	srand(time(nullptr));
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}
	showContainer(vec);

	sort(vec.begin(), vec.end());//默认从小到大排序
	showContainer(vec);

	//greater需要二元函数对象
	sort(vec.begin(), vec.end(), greater<int>());//从大到小排序
	showContainer(vec);

	/*
	把70按顺序插入到vec容器中 ->找第一个小于70的数字
	operator()(const T &val)
	greater a>b
	less a<b
	绑定器+二元函数对象=》一元函数对象
	bind1st:+greater bool operator()(70,const_Ty&_Right)
	bind2nd:+less bool operator()(const_Ty &_Left,70)
	*/
	auto it1 = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70));
	if (it1 != vec.end())
	{
		vec.insert(it1, 70);
	}
	showContainer(vec);
	return 0;
}

2.bind1st和bind2nd的底层原理实现

绑定器本身是一个函数对象

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
#include<ctime>
using namespace std;
template<typename Container>
void showContainer(Container& con)
{
	auto it = con.begin();
	for (; it != con.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
//遍历两个迭代器之间的元素,如果满足函数对象的运算,就返回当前的迭代器,如果都不满足就返回end
template<typename Iterator,typename Compare>
Iterator my_find_if(Iterator first, Iterator last, Compare comp)
{
	//这里传入的comp是封装好的一元函数对象
	for (; first != last; ++first)
	{
		if (comp(*first))//获取容器的一个元素
		{
			return first;
		}
	}
	return last;
}
template<typename Compare,typename T>
class _mybind1st//绑定器是函数对象的一个应用
{
public:
	//这里传入的comp是二元函数对象
	_mybind1st(Compare comp,T val)
		:_comp(comp),_val(val){}
	//通过重载operator()把二元函数对象封装为一元函数对象
	bool operator()(const T& second)
	{
		return _comp(_val, second);
	}
private:
	Compare _comp;
	T _val;
};
template<typename Compare,typename T>
_mybind1st<Compare, T> mybind1st(Compare comp, const T& val)
{
	//直接使用函数模板,好处是可以进行类型的推演
	//这里传入的comp是一个二元函数对象
	//通过二元函数对象构造一元函数对象
	//绑定器本身是一个函数对象,也就是重载了operator()
	return _mybind1st<Compare, T>(comp, val);
}
int main()
{
	vector<int> vec;
	srand(time(nullptr));
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}
	showContainer(vec);

	sort(vec.begin(), vec.end());//默认从小到大排序
	showContainer(vec);

	//greater需要二元函数对象
	sort(vec.begin(), vec.end(), greater<int>());//从大到小排序
	showContainer(vec);

	auto it1 = my_find_if(vec.begin(), vec.end(), mybind1st(greater<int>(), 70));
	if (it1 != vec.end())
	{
		vec.insert(it1, 70);
	}
	showContainer(vec);

	return 0;
}

二. 模板的完全特例化和非完全特例化

有完全特例化优先匹配完全特例化,有部分特例化就匹配部分特例化,没有的话就从原模板自己实例化

#include<iostream>
using namespace std;
template<typename T>
class Vector
{
public:
	Vector() { cout << "call Vector template init" << endl; }
};
//对char*类型提供完全特例化版本
template<>
class Vector<char*>
{
public:
	Vector() { cout << "call Vector<char*> init" << endl; }
};
//对指针类型提供的部分特例化版本(部分:只知道是个指针,但是指针的类型是什么不知道)
template<typename Ty>
class Vector<Ty*>
{
public:
	Vector() { cout << "call Vector<Ty*> init" << endl; }
};
//指针函数指针(有返回值,有两个形参变量)提供的部分特例化
template<typename R,typename A1,typename A2>
class Vector<R(*)(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(*)(A1,A2)> init" << endl; }
};
//针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(A1,A2)> init" << endl; }
};
int sum(int a, int b) { return a + b; }
int main()
{
	Vector<int> vec1;
	Vector<char*> vec2;
	Vector<int*> vec3;
	Vector<int(*)(int, int)> vec4;
	Vector<int(int, int)> vec5;

	//注意区分函数类型和函数指针类型
	typedef int(*PFUNC1)(int, int);
	PFUNC1 pfunc1 = sum;
	cout << pfunc1(10, 20) << endl;

	typedef int PFUNC2(int, int);
	PFUNC2* pfunc2 = sum;
	cout << (*pfunc2)(10, 20) << endl;
	return 0;
}

#include<iostream>
#include<typeinfo>
using namespace std;
//T包含了所有大的类型
template<typename T>
void func(T a)
{
	cout << typeid(T).name() << endl;
}
int sum(int a, int b) { return a + b; }

//把所有形参类型都取出来
template<typename R, typename A1, typename A2>
void func2(R(*a)(A1, A2))
{
	cout << typeid(R).name() << endl;
	cout << typeid(A1).name() << endl;
	cout << typeid(A2).name() << endl;
}
template<typename R,typename T,typename A1,typename A2>
void func3(R(T::*a)(A1, A2))
{
	cout << typeid(R).name() << endl;
	cout << typeid(T).name() << endl;
	cout << typeid(A1).name() << endl;
	cout << typeid(A2).name() << endl;
}
class Test
{
public:
	int sum(int a, int b) { return a + b; }
};
int main()
{
	//func(10);//int
	//func("aaa");//const char *
	func(sum);
	func2(sum);
	func3(&Test::sum);
	return 0;
}

三. function函数对象

绑定器,函数对象,lambda表达式本质上都是函数对象,只能使用在一条语句中,但是如果想要在多条语句中使用,就需要function

使用function函数需要注意:

  • 函数类型实例化function;
  • 通过function调用operator()函数的时候,需要根据函数类型传入相应的参数
#include<iostream>
#include<functional>
using namespace std;
void hello1()
{
	cout << "hello world!" << endl;
}
void hello2(string str)
{
	cout << str << endl;
}
int sum(int a, int b)
{
	return a + b;
}
int main()
{
	//从function的模板定义处,看到希望用一个函数类型实例化function
	function<void()> func1 = hello1;
	func1();//func1.operator() => hello1()

	function<void(string)> func2 = hello2;
	func2("hello hello2!");

	function<int(int, int)> func3 = sum;
	cout << func3(2, 3) << endl;

	function<int(int, int)> func4 = [](int a, int b)->int {return a + b; };
	cout << func4(3, 4) << endl;
	return 0;
}

function不仅可以留下普通全局函数的类型,对于类的成员方法也可以进行类型保留:

#include<iostream>
#include<functional>
using namespace std;

class Test
{
public://必须依赖一个对象void(Test::*pfunc)(string)
	void hello(string str) { cout << str << endl; }
};
int main()
{
	//成员方法一经编译都会多一个当前类型的this指针
	function<void (Test*, string)> func = &Test::hello;
	Test t;
	//对于成员方法的调用需要依赖一个成员对象
	func(&t, "call Test::hello!");
	return 0;
}

function的特点:可以把所有函数、绑定器、函数对象和lambda表达式的类型保留起来,在其他地方都可以使用。否则绑定器、lambda表达式就只能使用在语句中。

#include<iostream>
#include<functional>
#include<map>
using namespace std;
void doShowAllBooks(){ cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
void doQueryBooks() { cout << "查询书籍" << endl; }
void doLoginOut() { cout << "注销" << endl; }
int main()
{
	int choice = 0;
	//使用function函数对象完成
	map<int, function<void()>> actionMap;
	actionMap.insert({ 1,doShowAllBooks });
	actionMap.insert({ 2,doBorrow });
	actionMap.insert({ 3,doBack });
	actionMap.insert({ 4,doQueryBooks });
	actionMap.insert({ 5,doLoginOut });
	for (;;)
	{
		cout << "------------------" << endl;
		cout << "1.查看所有书籍信息" << endl;
		cout << "2.借书" << endl;
		cout << "3.还书" << endl;
		cout << "4.查询书籍" << endl;
		cout << "5.注销" << endl;
		cout << "------------------" << endl;
		cout << "请选择:";
		cin >> choice;

		auto it = actionMap.find(choice);
		if (it == actionMap.end())
		{
			cout << "输入数字无效,重新选择" << endl;
		}
		else
		{
			it->second();
		}
		//不好,因为这块代码无法闭合,无法做到“开-闭”原则,也就是说这块代码随着需求的更改需要一直改,永远也闭合不了,避免不了要产生很多问题
		/*
		switch(choice)
		{
			case 1:break;
			case 2:break;
			case 3:break;
			case 4:break;
			case 5:break;
			default:break;
		}
		*/
	}
	return 0;
}

function的实现原理:

#include<iostream>
#include<functional>
using namespace std;

void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }

template<typename Fty>
class myfunction{};
/*
template<typename R,typename A1>
class myfunction<R(A1)>
{
public:
	//typedef R(*PFUNC)(A1);
	using PFUNC = R(*)(A1);
	myfunction(PFUNC pfunc):_pfunc(pfunc){}
	R operator()(A1 arg)
	{
		return _pfunc(arg);
	}
private:
	PFUNC _pfunc;
};

template<typename R, typename A1,typename A2>
class myfunction<R(A1,A2)>
{
public:
	//typedef R(*PFUNC)(A1);
	using PFUNC = R(*)(A1,A2);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A1 arg1,A2 arg2)
	{
		return _pfunc(arg1,arg2);
	}
private:
	PFUNC _pfunc;
};
*/
//...表示可变参,A表示的是一组1类型,个数任意
template<typename R, typename... A>
class myfunction<R(A...)>
{
public:
	using PFUNC = R(*)(A...);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A... arg)
	{
		return _pfunc(arg...);
	}
private:
	PFUNC _pfunc;
};
int main()
{
	myfunction<void(string)> func1(hello);
	func1("hello world");
	myfunction<int(int, int)> func2(sum);
	cout << func2(10, 20) << endl;
	return 0;
}

四. bind和function实现线程池

#include<iostream>
#include<functional>
using namespace std;
using namespace placeholders;

//C++11 bind 绑定器=>返回的结果是一个函数对象
void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
class Test
{
public:
	int sum(int a, int b) { return a + b; }
};

int main()
{
	//bind是函数模板,可以自动推演模板类型参数
	bind(hello, "Hello bind!")();
	cout << bind(sum, 20, 30)() << endl;
	cout << bind(&Test::sum, Test(), 20, 30)() << endl;

	//function只接受一个类型,绑定器可以给相应的函数绑定固定的参数,绑定器只能使用在语句当中
	//参数占位符,绑定器出了语句,无法继续使用
	bind(hello, _1)("hello bind 2");
	cout << bind(sum, _1, _2)(20, 30) << endl;

	//此处把bind返回的绑定器binder就复用起来了
	function<void(string)> func1 = bind(hello, _1);
	func1("hello china!");
	func1("hello shan xi!");
	func1("hello da li!");

}
#include<iostream>
#include<functional>
#include<thread>
#include<vector>
using namespace std;
using namespace placeholders;

//线程类
class Thread
{
public:
	Thread(function<void(int)> func,int no):_func(func),_no(no){}
	thread start()
	{
		thread t(_func,_no);
		return t;
	}
private:
	function<void(int)> _func;
	int _no;
};
//线程池类
class ThreadPool
{
public:
	ThreadPool(){}
	~ThreadPool()
	{
		//释放thread对象占用的堆资源
		for (int i = 0; i < _pool.size(); i++)
		{
			delete _pool[i];
		}
	}
	//开启线程池
	void startPool(int size)
	{
		for (int i = 0; i < size; i++)
		{
			//不管是C++里面的thread还是Linux里面的pthread需要的线程函数都是一个C函数,是不能够使用成员方法的,因为它是C的函数类型,不可能把成员方法的函数指针给一个C的函数指针,接收不了。所以就需要绑定,把runInThread所依赖的参数全部绑定
			_pool.push_back(new Thread(bind(&ThreadPool::runInThread, this, _1),i));
		}
		for (int i = 0; i < size; i++)
		{
			_handler.push_back(_pool[i]->start());
		}
		for (thread& t : _handler)
		{
			t.join();
		}
	}
private:
	vector<Thread*> _pool;
	vector<thread> _handler;
	//把runInThread这个成员方法充当线程函数
	void runInThread(int id)
	{
		cout << "call runInThread! id:" << id << endl;
	}
};
int main()
{
	ThreadPool pool;
	pool.startPool(10);
	return 0;
}

五. lambda表达式

  • 函数对象的应用:使用在泛型算法参数传递、比较性质、自定义操作、优先级队列和智能指针
  • 函数对象的缺点:需要先定义一个函数对象类型,但是类型定义完后可能只是用在了定义的地方,后面可能不会再用了,没有必要为了需要一个函数对象定义一个类型,这个类型就永远在代码当中。

C++11函数对象的升级版 => lambda表达式:

  • lambda表达式:底层依赖函数对象的机制实现的
  • lambda表达式语法:[捕获外部变量](形参列表) ->返回值{操作代码};

如果lambda表达式的返回值不需要,那么“->返回值”可以省略

[捕获外部变量]

  • [ ]:表示不捕获任何外部变量
  • [=]:以传值的方式捕获外部的所有变量
  • [&]:以传引用的方式捕获外部的所有变量[this]:捕获外部的this指针
  • [=,&a]:以传值的方式捕获外部的所有变量,但是a变量以传引用的方式捕获
  • [a,b]:以传值的方式捕获外部变量a和b
  • [a,&b]:a以值传递捕获,b以传引用的方式捕获

1.lambda表达式的实现原理

#include<iostream>
using namespace std;
template<typename T=void>
class TestLambda01
{
public:
	void operator()()
	{
		cout << "hello world" << endl;
	}
};
template<typename T = int>
class TestLambda02
{
public:
	TestLambda02() {}
	int operator()(int a, int b)
	{
		return a + b;
	}
};
template<typename T = int>
class TestLambda03
{
public:
	TestLambda03(int a,int b):ma(a),mb(b){}
	void operator()()const
	{
		int tmp = ma;
		ma = mb;
		mb = tmp;
	}
private:
	mutable int ma;
	mutable int mb;
};
class TestLambda04
{
public:
	TestLambda04(int &a,int &b):ma(a),mb(b){}
	void operator()()const
	{
		int tmp = ma;
		ma = mb;
		mb = tmp;
	}
private:
	int& ma;
	int& mb;
};
int main()
{
	auto func1 = []()->void {cout << "hello world" << endl; };
	func1();

	auto func2 = [](int a, int b)->int {return a + b; };
	cout << func2(20, 30) << endl;

	int a = 10;
	int b = 20;
	//按值传递a,b值未被改变
	auto func3 = [a, b]()mutable
	{
		int tmp = a;
		a = b;
		b = tmp;
	};
	func3();
	cout << "a:" << a << " b:" << b << endl;

	//传引用值a,b值被改变
	auto func4 = [&]()
	{
		int tmp = a;
		a = b;
		b = tmp;
	};
	func4();
	cout << "a:" << a << " b:" << b << endl;

	cout << "--------------------" << endl;
	TestLambda01<> t1;
	t1();
	TestLambda02<> t2;
	cout << t2(20, 30) << endl;
	TestLambda03<> t3(a,b);
	t3();
	cout << "a:" << a << " b:" << b << endl;
	TestLambda04 t4(a,b);
	t4();
	cout << "a:" << a << " b:" << b << endl;

	return 0;
}

mutable:成员变量本身也不是常量,只不过在常方法中this指针被修饰成const,在声明成员变量前加mutable,可以在const方法中修改普通的成员变量

lambda表达式后面修饰mutable相当于在它的所有成员变量添加一个mutable修饰。

2.lambda表达式的应用实践

lambda表达式应用于泛型算法:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	vector<int> vec;
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}
	sort(vec.begin(), vec.end(),
		[](int a, int b)->bool
		{
			return a > b;
		});
	for (int val : vec)
	{
		cout << val << " ";
	}
	cout << endl;
	//65按序插入序列 要找一个小于65的数字
	auto it = find_if(vec.begin(), vec.end(),
		[](int a)->bool {return a < 65; });
	if (it != vec.end())
	{
		vec.insert(it, 65);
	}
	for (int val : vec)
	{
		cout << val << " ";
	}
	cout << endl;
	for_each(vec.begin(), vec.end(), [](int a)
	{
		if (a % 2 == 0)
			cout << a << " ";
	});
	cout << endl;
	return 0;
}

既然lambda表达式只能使用在语句中,如果想跨语句使用之前定义好的lambda表达式,采用function类型来表示函数对象的类型。

哈希表的应用:

#include<iostream>
#include<vector>
#include<map>
#include<functional>
using namespace std;
int main()
{
	//auto只能出现在根据右边表达式推导左边的类型,只能使用在函数的局部作用域的范围之内
	//预先lambda表达式不知道需要先存储lambda表达式类型
	map<int, function<int(int, int)>> caculateMap;
	caculateMap[1] = [](int a, int b)->int {return a + b; };
	caculateMap[2] = [](int a, int b)->int {return a - b; };
	caculateMap[3] = [](int a, int b)->int {return a * b; };
	caculateMap[4] = [](int a, int b)->int {return a / b; };

	cout << "请选择";
	int choice;
	cin >> choice;
	cout << caculateMap[choice](10, 15) << endl;
	return 0;
}

智能指针自定义删除器:

#include<iostream>
#include<vector>
#include<functional>
using namespace std;
int main()
{
	unique_ptr<FILE, function<void(FILE*)>>
		ptr1(fopen("data.txt", "w"), [](FILE* pf) {fclose(pf); });
}

传入函数对象使得容器元素按照指定方式排列:

#include<iostream>
#include<vector>
#include<functional>
#include <queue>
using namespace std;

class Data
{
public:
	Data(int val1=10,int val2=10):ma(val1),mb(val2){}
	int ma;
	int mb;
};
int main()
{
	//优先级队列
	//priority_queue<Data> queue;
	using FUNC = function<bool(Data&, Data&)>;
	priority_queue<Data, vector<Data>, FUNC>
		maxHeap([](Data& d1, Data& d2)->bool
			{
				return d1.mb > d2.mb;
			});
	maxHeap.push(Data(10, 20));
	maxHeap.push(Data(15, 15));
	maxHeap.push(Data(20, 10));
}

到此这篇关于C++11中bind绑定器和function函数对象介绍的文章就介绍到这了,更多相关C++bind绑定器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++11 学习笔记之std::function和bind绑定器

    std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法五花八门.为了统一泛化函数对象,函数指针,引用函数,成员函数的指针的各种操作,让我们可以按更统一的方式写出更加泛化的代码,C++11推出了std::function. std::function是可调用对象的包装器.它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象.通过指定它的模板参数,它可以用统一的方式处理函数,函数对象,函数指针,并允许保存和延迟

  • C++中使用function和bind绑定类成员函数的方法详解

    定义一个普通的类 class Test1{ public: void fun(int val){ cout<<"hello world "<<val<<endl; } }; 开始第一个测试 int main(){ Test1 t; function<void(int)> pf = std::bind(&Test1::fun,t,2); pf(4); // return 0; } 输出的值是2,说明pf传进去的4并没有什么用,在bi

  • c++11 符号修饰与函数签名、函数指针、匿名函数、仿函数、std::function与std::bind

    一.符号修饰与函数签名 1.符号修饰 编译器将c++源代码编译成目标文件时,用函数签名的信息对函数名进行改编,形成修饰名.GCC的C++符号修饰方法如下: 1)所有符号都以_z开头 2)名字空间的名字 名字空间(或类)的名字前加上N 名字前还有一个数字,是名字的字符数.比如1C,1是C的长度. 3)函数名 与名字空间一样,函数名前也有数字,比如4func,4是func的字符数. 4)参数 参数以E开头 例子 N::C::func(int) 的函数签名经过修饰为_ZN1N1C4funcEi 2.函

  • C++类重载函数的function和bind使用示例

    在没有C++11的std::function和std::bind之前,我们使用函数指针的方式是五花八门,结构很繁琐难懂.C++11中提供了std::function和std::bind统一了可调用对象的各种操作. 1.std::function简介 std::function首先是可调用对象,本质上生成了一个类(仿函数) 简单的使用如下代码 #include <unordered_map> #include <iostream> #include <functional>

  • 详解C++ functional库中的仿函数使用方法

    目录 一.仿函数简介 二.仿函数简要写法示例 三.使用C++自带的仿函数 (1)算术仿函数 (2)关系仿函数 (3)逻辑仿函数 一.仿函数简介 仿函数(functor)又称之为函数对象(function object),实际上就是 重载了()操作符 的 struct或class.由于重载了()操作符,所以使用他的时候就像在调用函数一样,于是就被称为“仿”函数啦. 二.仿函数简要写法示例 一个很正常的需求,定义一个仿函数作为一个数组的排序规则: 将数组从大到小排序 class Cmp { publ

  • 理解C++编程中的std::function函数封装

    先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; 这两行代码是从Cocos2d-x中摘出来的,重点是这两行代码的定义啊.std::function这是什么东西?如果你对上述两行代码表示毫无压力,那就不妨再看看本文,就当温故而知新吧. std::

  • C++11中bind绑定器和function函数对象介绍

    目录 一. bind1st和bind2nd 1.C++ STL中的绑定器 2.bind1st和bind2nd的底层原理实现 二. 模板的完全特例化和非完全特例化 三. function函数对象 四. bind和function实现线程池 五. lambda表达式 1.lambda表达式的实现原理 2.lambda表达式的应用实践 一. bind1st和bind2nd 1.C++ STL中的绑定器 bind1st:operator()的第一个形参变量绑定成一个确定的值 bind2nd:operat

  • JavaScript的function函数详细介绍

    通过函数来封装任意多条语句,而且可以在任何地方.任何时间调用执行. 而我们的JavaScript脚本语言比较特殊,相对于C语言,它的参数是不需要数据类型加持的.返回值return,我就不过多描述,他是和 C语言通的,如果没写他就会自动返回undefined function fun(x,y){ } //写成这样就可以声明一个函数 以我的理解他就是以对象的形式来传入参数,通过对象的各项属性值(引用类型的值),来作为我的实际参数, 例如我有以下做法: function fun(x, y) { //

  • JavaScript Function函数类型介绍

    // 在JS中,Function(函数)类型实际上是对象;每个函数都是Function类型的实例;而且都与其他引用类型一样具有属性和方法; // 由于函数是对象,因此函数名实际上也是一个指向函数对象的指针; 一 函数的声明方式 1.函数声明方式 function box(num1,num2){ return num1+num2; } 2.函数表达式定义函数 var box = function(num1,num2){ // 通过变量box即可引用函数; return num1+num2; };

  • javascript中的绑定与解绑函数应用示例

    Mozilla中: addEventListener的使用方式: target.addEventListener(type, listener, useCapture); target: 文档节点.document.window 或 XMLHttpRequest. type: 字符串,事件名称,不含"on",比如"click"."mouseover"."keydown"等. listener :实现了 EventListene

  • jQuery中bind(),live(),delegate(),on()绑定事件方法实例详解

    本文实例分析了jQuery中bind(),live(),delegate(),on()绑定事件方法.分享给大家供大家参考,具体如下: 前言 因为项目中经常会有利用jquery操作dom元素的增删操作,所以会涉及到dom元素的绑定事件方式,简单的归纳一下bind,live,delegate,on的区别,以便以后查阅,也希望该文章日后能帮助到各位朋友,文中如有不当之处,还望各位指正,话不多说,直接进入正题. 一.bind() 简要描述 bind()向匹配元素添加一个或多个事件处理器. 使用方式 复制

  • C++11 中的override详解

    目录 1 公有继承 1.1 纯虚函数 (pure virtual) 1.2 普通虚函数 1.2.1 方法一 1.2.2 方法二 1.3 非虚函数 2 重写 (override) 小结: 参考资料 1 公有继承 公有继承包含两部分:一是"函数接口" (interface),二是"函数实现" (implementation) 如 Shape 类中,三个成员函数,对应三种继承方式: class Shape { public: virtual void Draw() con

  • 详解C++11中模板的优化问题

    1. 模板的右尖括号 在泛型编程中,模板实例化有一个非常繁琐的地方,那就是连续的两个右尖括号(>>)会被编译器解析成右移操作符,而不是模板参数表的结束.我们先来看一段关于容器遍历的代码,在创建的类模板 Base 中提供了遍历容器的操作函数 traversal(): // test.cpp #include <iostream> #include <vector> using namespace std; template <typename T> class

  • C++11中使用using的方法

    在 C++ 中 using 用于声明命名空间,使用命名空间也可以防止命名冲突.在程序中声明了命名空间之后,就可以直接使用命名空间中的定义的类了.在 C++11 中赋予了 using 新的功能,让 C++ 变得更年轻,更灵活. 1. 定义别名 在 C++ 中可以通过 typedef 重定义一个类型,语法格式如下: typedef 旧的类型名 新的类型名; // 使用举例 typedef unsigned int uint_t; 被重定义的类型并不是一个新的类型,仅仅只是原有的类型取了一个新的名字.

  • 浅谈C++11中的几种锁

    目录 互斥锁(mutex) 条件锁(condition_variable) 自旋锁(不推荐使用) 递归锁(recursive_mutex) 互斥锁(mutex) 可以避免多个线程在某一时刻同时操作一个共享资源,标准C++库提供了std::unique_lock类模板,实现了互斥锁的RAII惯用语法:eg: std::unique_lock<std::mutex> lk(mtx_sync_); 条件锁(condition_variable) 条件锁就是所谓的条件变量,某一个线程因为某个条件未满足

随机推荐