`
piperzero
  • 浏览: 3466375 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

复习C++基础知识-----“我的第一本C++”读书笔记4(终篇)

 
阅读更多
怎样选择STL容器类型
vector : 需要保存大量数据的时候
map : 用来实现查找表,或者用来存储稀疏数组或稀疏矩阵
list : 频繁地对序列的中部进行插入和删除操作
deque : 当大部分插入和删除发生在序列的头部或尾部时
array : 固定长度的数组


STL算法
1)用for_each()算法遍历容器中的数据元素

for_each()的参数分别是开始位置、结束位置、处理函数

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const int iValue ) 
{
	cout << "current value add 10 : " << iValue + 10 << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> vecSalary;
	vecSalary.push_back( 10 );
	vecSalary.push_back( 20 );
	vecSalary.push_back( 30 );
	vecSalary.push_back( 40 );
	vecSalary.push_back( 50 );

	cout << "display the value:" << endl;
	for_each( vecSalary.begin(), vecSalary.end(), vecDisplay );


	return 0;
}

2)用find算法实现线性查找-----判断容器中是否存在特定的数据

find()的参数分别是开始位置、结束位置、要查找的数据

#include "stdafx.h"
#include "vector"
#include "algorithm"
#include "string"
#include "iostream"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{

	vector<string> vecStudentName;
	vecStudentName.push_back( "zengraoli" );
	vecStudentName.push_back( "125308501" );
	vecStudentName.push_back( "test" );
	vecStudentName.push_back( "find" );

	const string strFindName = "125308501";
	vector<string>::iterator it = find( vecStudentName.begin(), vecStudentName.end(), strFindName );
	if (vecStudentName.end() != it)
	{
		cout << "vecStudentName is exist this string 125308501 !" << endl;
	}
	it = find( vecStudentName.begin(), vecStudentName.end(), "125308502" );
	if ( vecStudentName.end() == it )
	{
		cout << "vecStudentName isn't exist this string 125308502 !" << endl;
	}


	return 0;
}

3)用find_if()算法实现线性查找-----判断容器中是否存在指定范围的数据

find_if()的参数分别是开始位置、结束位置、所定义的要查找的条件(以bool(int)函数来表示)


#include "stdafx.h"
#include "iostream"
using namespace std;
#include "algorithm"
#include "vector"

#define FIND_VALUE_TERMS 6

bool isPass( int n )
{
	return n >= FIND_VALUE_TERMS;
}

void vecDisplay( int iValue )
{
	cout << "current container value is : " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> vecScores;
	for ( int i = 1; i <= 10; i++ )
	{
		vecScores.push_back( i );
	}

	vector< int >::iterator it = vecScores.begin();
	do 
	{
		it = find_if( it, vecScores.end(), isPass );
		if (it != vecScores.end())
		{
			cout << "meet the conditions : " << ( *it ) << endl;
			it++; // this iterator point next
		}
		else
		{
			break;
		}
	} while (true);

	return 0;
}

4)用remove()实现移除、replace()实现替换

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "algorithm"
#include "vector"

#define FIND_VALUE_TERMS 6

void vecDisplay( int iValue )
{
	cout << "current container value is : " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> vecScores;
	for ( int i = 1; i <= 10; i++ )
	{
		vecScores.push_back( i );
	//	vecScores.push_back( 9 );
	}

	cout << "used function remove" << endl;
	const int removeValue = 8;
	remove( vecScores.begin(), vecScores.end(), removeValue );
	for_each( vecScores.begin(), vecScores.end(), vecDisplay );

	cout << "\n";
	cout << "used function replace" << endl;
	const int replaceValue = 9;
	const int newValue = 999;
	replace( vecScores.begin(), vecScores.end(),replaceValue, newValue );
	for_each( vecScores.begin(), vecScores.end(), vecDisplay );

	return 0;
}

5)复制容器元素 : copy()

有时需要将一个容器中的元素复制到另一个容器中区,来完成数据的备份或者进行其他处理。
vector<float>::iterator lastPos在使用的时候,指向的是某个具体的数据而不是该数据的pos。

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const int iValue ) 
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<float> vecScoreFirst;
	vector<float> vecScoreSecond;
	vector<float> vecScore;

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreFirst.push_back( 60.0f + i );
	}
	cout << "vecScoreFirst current value:" << endl;
	for_each( vecScoreFirst.begin(), vecScoreFirst.end(), vecDisplay );

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreSecond.push_back( 80.0f + i );
	}
	cout << "\n" << endl;
	cout << "vecScoreSecond current value:" << endl;
	for_each( vecScoreSecond.begin(), vecScoreSecond.end(), vecDisplay );


	vecScore.resize( vecScoreFirst.size() + vecScoreSecond.size() ); // resize vecScore
	vector< float >::iterator lastPos = copy( vecScoreFirst.begin(), vecScoreFirst.end(), vecScore.begin() );
	copy( vecScoreSecond.begin(), vecScoreSecond.end(), lastPos );

	cout << "\n" << endl;
	cout << "vecScore current value:" << endl;
	for_each( vecScore.begin(), vecScore.end(), vecDisplay );

	return 0;
}

6)复制容器元素 : copy_backward()
从后向前覆盖

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const int iValue ) 
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<float> vecScoreFirst;
	vector<float> vecScoreSecond;
	vector<float> vecScore;

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreFirst.push_back( 60.0f + i );
	}
	cout << "vecScoreFirst current value:" << endl;
	for_each( vecScoreFirst.begin(), vecScoreFirst.end(), vecDisplay );

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreSecond.push_back( 80.0f + i );
	}
	cout << "\n" << endl;
	cout << "vecScoreSecond current value:" << endl;
	for_each( vecScoreSecond.begin(), vecScoreSecond.end(), vecDisplay );

	cout << "\n" << endl;
	vecScore.resize( vecScoreFirst.size() + vecScoreSecond.size() ); // resize vecScore
	cout << "vecScore size is : " << vecScore.size() << endl;

	copy( vecScoreFirst.begin(), vecScoreFirst.end(), vecScore.begin() );
	copy_backward( vecScoreSecond.begin(), vecScoreSecond.end(), vecScore.end() );

	cout << "\n" << endl;
	cout << "vecScore current value:" << endl;
	for_each( vecScore.begin(), vecScore.end(), vecDisplay );

	return 0;
}


7)合并容器元素 : merge()
类似copy的用法

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const int iValue ) 
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<float> vecScoreFirst;
	vector<float> vecScoreSecond;
	vector<float> vecResutl;

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreFirst.push_back( 60.0f + i );
	}
	cout << "vecScoreFirst current value:" << endl;
	for_each( vecScoreFirst.begin(), vecScoreFirst.end(), vecDisplay );

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreSecond.push_back( 60.0f + i );
	}
	cout << "\n" << endl;
	cout << "vecScoreSecond current value:" << endl;
	for_each( vecScoreSecond.begin(), vecScoreSecond.end(), vecDisplay );


	// used merge the two container must to pass through sort, otherwise error
	vecResutl.resize( vecScoreFirst.size() + vecScoreSecond.size() );
	merge( vecScoreFirst.begin(), vecScoreFirst.end(), vecScoreSecond.begin(), vecScoreSecond.end(), vecResutl.begin() );

	cout << "\n" << endl;
	cout << "vecScore current value:" << endl;
	for_each( vecResutl.begin(), vecResutl.end(), vecDisplay );

	return 0;
}

8)set_union()
合并之后去掉两个容器中重复的部分

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const int iValue ) 
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<float> vecScoreFirst;
	vector<float> vecScoreSecond;
	vector<float> vecResutl;

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreFirst.push_back( 60.0f + i );
	}
	cout << "vecScoreFirst current value:" << endl;
	for_each( vecScoreFirst.begin(), vecScoreFirst.end(), vecDisplay );

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreSecond.push_back( 60.0f + i );
	}
	cout << "\n" << endl;
	cout << "vecScoreSecond current value:" << endl;
	for_each( vecScoreSecond.begin(), vecScoreSecond.end(), vecDisplay );


	// used merge the two container must to pass through sort, otherwise error
	vecResutl.resize( vecScoreFirst.size() + vecScoreSecond.size() );
	set_union( vecScoreFirst.begin(), vecScoreFirst.end(), vecScoreSecond.begin(), vecScoreSecond.end(), vecResutl.begin() );

	cout << "\n" << endl;
	cout << "vecScore current value:" << endl;
	for_each( vecResutl.begin(), vecResutl.end(), vecDisplay );

	return 0;
}

9)transform()
在进行元素的复制时,同时对元素进行某些操作
transform有两种使用方式,分别对应的func参数不同

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

#define ADD_VALUE 10

// used transform the first form
int firstAddFunc( int iValue )
{
	return iValue + ADD_VALUE;
}

// used transform the first form
int secondAddFunc( int iLeftValue, int iRightValue )
{
	return iLeftValue + iRightValue;
}

void vecDisplay( int iValue )
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<float> vecScoreFirst;
	vector<float> vecScoreSecond;
	vector<float> vecResutl;

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreFirst.push_back( 60.0f + i );
	}
	cout << "vecScoreFirst current value:" << endl;
	for_each( vecScoreFirst.begin(), vecScoreFirst.end(), vecDisplay );

	for ( int i = 0; i < 10; i++ )
	{
		vecScoreSecond.push_back( 80.0f + i );
	}
	cout << "\n" << endl;
	cout << "vecScoreSecond current value:" << endl;
	for_each( vecScoreSecond.begin(), vecScoreSecond.end(), vecDisplay );

	// used transform the first form
	vecResutl.resize( vecScoreFirst.size() );
	transform( vecScoreFirst.begin(), vecScoreFirst.end(), vecResutl.begin(), firstAddFunc );
	cout << "\n" << endl;
	cout << "transform the first form vecScore current value:" << endl;
	for_each( vecResutl.begin(), vecResutl.end(), vecDisplay );

	// used transform the second form
	vecResutl.clear();
	vecResutl.resize( vecScoreFirst.size() );
	transform( vecScoreFirst.begin(), vecScoreFirst.end(), vecScoreSecond.begin(), vecResutl.begin(), secondAddFunc );
	cout << "\n" << endl;
	cout << "transform the second form vecScore current value:" << endl;
	for_each( vecResutl.begin(), vecResutl.end(), vecDisplay );

	return 0;
}

10)sort()、reverse()
排序和翻转算法

#include "stdafx.h"
#include "string"
#include "iostream"
using namespace std;
#include "vector"
#include "algorithm"

void vecDisplay( const string iValue ) 
{
	cout << "current container value is: " << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<string> vecStudentName;
	vector<string>::iterator it;
	vecStudentName.push_back( "zeng" );
	vecStudentName.push_back( "zengraoli" );
	vecStudentName.push_back( "zengRaoli" );
	vecStudentName.push_back( "test" );
	vecStudentName.push_back( "125308501" );
	vecStudentName.push_back( "zengRaoli2" );
	vecStudentName.push_back( "1zeng" );

	cout << "vecStudentName current value:" << endl;
	for( it = vecStudentName.begin(); it != vecStudentName.end(); it++ )
	{
		cout << "vecScore current value:" << ( *it ) << endl;
	}

	// used sort algorithm
	sort( vecStudentName.begin(), vecStudentName.end() );
	cout << "\n" << endl;
	cout << "pass sort vecStudentName current value:" << endl;
	for_each( vecStudentName.begin(), vecStudentName.end(), vecDisplay );

	// used reverse algorithm
	reverse( vecStudentName.begin(), vecStudentName.end() );
	cout << "\n" << endl;
	cout << "pass reverse vecStudentName current value:" << endl;
	for_each( vecStudentName.begin(), vecStudentName.end(), vecDisplay );

	return 0;
}


更改对基本数据类型的sort算法:

#include "stdafx.h"
#include "string"
#include "vector"
#include "algorithm"
#include "assert.h"
#include "iostream"
using namespace std;

void vecDisplay( const int iValue )
{
	cout << "current value is " << iValue << endl;
}

// my sort algorithm
bool defineSort( const int iLeftValue, const int iRightValue )
{
	return ( iLeftValue > iRightValue );
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> vecIValue;
	vecIValue.push_back( 9 );
	vecIValue.push_back( 1 );
	vecIValue.push_back( 3 );
	vecIValue.push_back( 5 );
	vecIValue.push_back( 8 );
	vecIValue.push_back( 7 );
	vecIValue.push_back( 2 );

/*
	sort( vecIValue.begin(), vecIValue.end() );
	cout << "pass sort : " << endl;
	for_each( vecIValue.begin(), vecIValue.end(), vecDisplay );
*/
	
	sort( vecIValue.begin(), vecIValue.end(), defineSort );
	cout << "pass sort : " << endl;
	for_each( vecIValue.begin(), vecIValue.end(), vecDisplay );


	return 0;
}

针对于自定义类型的sort算法
需要重写 < 号,暂时类里面不带有指针变量,否则还要重写拷贝构造

#include "stdafx.h"
#include "string"
#include "vector"
#include "algorithm"
#include "assert.h"
#include "iostream"
using namespace std;

namespace Zeng
{
	class CTest_Rectang
	{
	public:
		CTest_Rectang( int iLong, int iWidth, int iHeight )
			: m_iLong( iLong ), m_iWidth( iWidth ), m_iHeight( iHeight )
		{
		}
		bool operator < ( const CTest_Rectang& rCTest_Rectang )
		{
			assert( rCTest_Rectang.m_iLong );
			if ( rCTest_Rectang.m_iLong > this->m_iLong )
			{
				return true;
			}
			return false;
		}
		friend void vecDisplay( const CTest_Rectang& rCTest_Rectang );
	private:
		int m_iLong;
		int m_iWidth;
		int m_iHeight;
	};
	void vecDisplay( const Zeng::CTest_Rectang& rCTest_Rectang ) 
	{
		cout << "current container Zeng::CTest_Rectang m_iLong is: " << rCTest_Rectang.m_iLong << endl;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<Zeng::CTest_Rectang> vecCTestRectang;
	for ( int i = 0; i < 8; i++ )
	{
		vecCTestRectang.push_back( Zeng::CTest_Rectang( 14 + i, 14, 14 ) );
	}

	// used sort algorithm
	sort( vecCTestRectang.begin(), vecCTestRectang.end() );
	cout << "\n" << endl;
	cout << "pass sort vecStudentName current value:" << endl;
	for_each( vecCTestRectang.begin(), vecCTestRectang.end(), Zeng::vecDisplay );

	// used reverse algorithm
	reverse( vecCTestRectang.begin(), vecCTestRectang.end() );
	cout << "\n" << endl;
	cout << "pass reverse vecStudentName current value:" << endl;
	for_each( vecCTestRectang.begin(), vecCTestRectang.end(), Zeng::vecDisplay );

	return 0;
}

11)min_element()、max_element()
取最大最小值算法,容器需要经过sort排序
找到后输出后面的全部值

#include "stdafx.h"
#include "string"
#include "vector"
#include "algorithm"
#include "assert.h"
#include "iostream"
using namespace std;

void vecDisplay( const int iValue )
{
	cout << "current value is " << iValue << endl;
}

// my sort algorithm
bool defineSort( const int iLeftValue, const int iRightValue )
{
	return ( iLeftValue > iRightValue );
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> vecIValue;
	vecIValue.push_back( 7 );
	vecIValue.push_back( 8 );
	vecIValue.push_back( 3 );
	vecIValue.push_back( 1 );
	vecIValue.push_back( 9 );
	vecIValue.push_back( 5 );
	vecIValue.push_back( 2 );

	vector<int>::iterator it;
	it = max_element( vecIValue.begin(), vecIValue.end() );
	for ( ; it != vecIValue.end(); it++ )
	{
		cout << "max_element current value is : " << ( *it ) << endl;
	}

	cout << "\n" << endl;
	it = min_element( vecIValue.begin(), vecIValue.end() );
	for ( ; it != vecIValue.end(); it++ )
	{
		cout << "min_element current value is : " << ( *it ) << endl;
	}

	return 0;
}

函数指针
1)
根据函数指针所指向函数的不同,需要根据函数的具体声明来定义一个函数指针,其语法格式如下:
函数返回值类型标识符 ( 指针变量名 )( 形参列表 );
由于"()"的优先级高于"*",所以指针变量名外的括号必不可少。形参列表表示指针变量指向的函数所带的参数列表。
2)
例如有一个函数
void PrintPass( int iLeft, int iRightValue );
如果要声明一个函数指针
void ( *pFunc )( int iLeft, int iRightValue );
省略形参后
void ( *pFunc )( int, int );
如果要定义多个同一类型的指针,还可以使用typedef关键字定义一种新的函数之着呢的数据类型,用这种新的数据类型来定义函数指针,例如
// 定义一种新的函数指针的数据类型
typedef bool ( *pFunc )( int, int );
// 使用新的数据类型定义函数指针
pFunc pMax;
// 直接指向函数
pMax = Max;

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

typedef bool ( *pFunc )( int, int );

bool Max( const int iLeftValue, const int iRightValue )
{
	return ( iLeftValue > iRightValue );
}

int _tmain(int argc, _TCHAR* argv[])
{
	pFunc pMax;
	pMax = Max;
	cout << "pMax( 5, 6 ) this return bool value is : " << pMax( 5, 6 ) << endl;
	cout << "pMax( 6, 5 ) this return bool value is : " << pMax( 6, 5 ) << endl;

	return 0;
}

3)
可以在声明的时候不使用typedef直接用auto作为函数指针的数据类型来声明一个函数指针,
auto pMax = Max; // 只能在vs2010上面才使用有效

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

int Max( const int iLeftValue, const int iRightValue )
{
	return ( iLeftValue > iRightValue );
}

int _tmain(int argc, _TCHAR* argv[])
{
	auto pMaxSendcont = Max;
	cout << "pMaxSendcont( 5, 6 ) this return bool value is : " << pMaxSendcont( 5, 6 ) << endl;
	cout << "pMaxSendcont( 6, 5 ) this return bool value is : " << pMaxSendcont( 6, 5 ) << endl;
	return 0;
}

用函数指针实现回调函数
1)
回调函数就是一个通过函数指针调用的函数。如果吧函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,就说这事回调函数。回调函数不是由该函数的实现方直接

调用,而是特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
2)
回调函数实现的机制是:
a、定义一个回调函数
b、提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者
c、当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理
3)为什么要使用回调函数
因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数

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

typedef bool ( *PMAXFUNC )( int, int );

void PrintMessage( int iLeftValue, int iRightValue, PMAXFUNC pMax )
{
	cout << "Print Header :" << endl;
	cout << "====================================================" << endl;
	cout << "pMax LeftValue is : " << iLeftValue << endl;
	cout << "pMax RightValue is : " << iRightValue << endl;
	cout << "pMax function return is : " << pMax( iLeftValue, iRightValue ) << endl;
	cout << "====================================================" << endl;
	cout << "Print ender :" << endl;
}

bool Max( const int iLeftValue, const int iRightValue )
{
	return ( iLeftValue > iRightValue );
}

int _tmain(int argc, _TCHAR* argv[])
{
	PMAXFUNC pMax = Max;
	PrintMessage( 5, 6, pMax );

	return 0;
}

4)将函数指针应用到STL算法中
ptr_fun()函数将一个普通函数指针转换为一个函数对象
bind1st()函数将整个函数对象的第一个参数绑定为nStandardHeigth

a、在count_if()算法中实现规则和统计标准的完全自定义:

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

#define STANDARHEIGHT	165
#define STUDENTNUM		5

class CStudent
{
public:
	CStudent( int iHeight ) : m_iHeight( iHeight )
	{
	}
	int GetHeight() const
	{
		return m_iHeight;
	}
private:
	int m_iHeight;
};

bool countHeight( int iHeight, const CStudent st)
{
	return st.GetHeight() > iHeight;
}

int _tmain(int argc, _TCHAR* argv[])
{
	vector<CStudent> vecStudent;
	for (int i = 0; i < STUDENTNUM; i++)
	{
		vecStudent.push_back( CStudent( STANDARHEIGHT - 10 + i * 10 ) );
	}

	const int nStandarHeight = STANDARHEIGHT;
	int iCount = count_if( vecStudent.begin(), vecStudent.end(), bind1st( ptr_fun( countHeight ), nStandarHeight ) );

	cout << "the student height greater than Standar Number is : " << iCount << endl;

	return 0;
}

bind1st()函数将整个函数对象的第一个参数绑定为nStandardHeigth,而函数对象的第二个参数就是iron国企中的CStudent对象作为参数调用countHeight()这个重新定义的统计规则函数,以实现

统计规则和统计标准的完全自定义。

b、在算法中使用指向某个类的成员函数的函数指针

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

class CStudent
{
public:
	CStudent( string strName )
	{
		m_strName = strName;
	}
	bool isNamed( string strName )
	{
		return strName == m_strName;
	}
private:
	string m_strName;
};


int _tmain(int argc, _TCHAR* argv[])
{
	vector<CStudent> vecStudent;
	vecStudent.push_back( CStudent( "zengraoli1" ) );
	vecStudent.push_back( CStudent( "zengraoli2" ) );
	vecStudent.push_back( CStudent( "zengraoli3" ) );
	
	string strFindName = "zengraoli2";
	vector<CStudent>::iterator it = find_if( vecStudent.begin(), vecStudent.end(),
											 bind2nd( mem_fun_ref( &CStudent::isNamed ), strFindName ) );
	if ( it != vecStudent.end() )
	{
		cout << "找到了对应的vecStudent!" << endl;
	}

	return 0;
}

在这段代码中,&CStudent::isNamed去的成员函数isNamed()的地址,也就是获得了指向这个成员函数的函数指针;然后使用mem_fun_ref()函数将这个函数指针构造成一个函数对象,如果容器中保存的是指向对象的指针,就应该使用mem_fun_ref()函数来完成这一任务。
因为这个成员函数需要一个蚕食,所以更进一步的,使用bind2nd()函数绑定其第二个参数strFindName来作为查找条件。因为这是一个类的成员函数指针,所以容器中的对象会作为默认隐含的第一个参数。

=====================================================================
函数指针配合STL算法的应用,将STL算法的通用性发挥到了极致。


函数对象
1)所谓函数对象,就是定义了函数调用操作符(function-call operator),即operator()的普通类的对象。在重载的函数调用操作符中,可以实现函数的所有功能。同事,因为类具有属性,可以将每次

函数调用的状态数据保存到他的属性中,这样函数对象就不会像函数指针那样失忆了,从而可以应用在更广的范围内。
2)定义一个模板函数对象
------------------------------------------------------

template <typename T>
class myMax
{
	T operator()(T a, T b)
	{
		return ( a > b ? a : b );
	}
};

3)在STL中使用函数对象
------------------------------------------------------

#include "stdafx.h"
#include "vector"
#include "algorithm"
#include "iostream"
using namespace std;

namespace Zeng
{
	class CStudent
	{
	public:
		CStudent( int nHeight ) : m_nHieght( nHeight ) 
		{
		}
		int GetHeight()
		{
			return m_nHieght;
		}
	private:
		int m_nHieght;
	};

	class CAverageHeight
	{
	public:
		CAverageHeight() : m_nCount( 0 ), m_nTotalHeight( 0 )
		{
		}
		void operator ()( CStudent st )
		{
			m_nTotalHeight += st.GetHeight();
			m_nCount++;
		}
		int GetCount()
		{
			return m_nCount;
		}
		int GetTotalHeight()
		{
			return m_nTotalHeight;
		}
		float GetAverageHeight()
		{
			if ( 0 != m_nCount )
			{
				return static_cast<float>( GetTotalHeight() / GetCount() );
			}
			return 0;
		}
	private:
		int m_nCount;
		int m_nTotalHeight;
	};
}


int _tmain(int argc, _TCHAR* argv[])
{
	vector<Zeng::CStudent> vecStudent;
	vecStudent.push_back( Zeng::CStudent( 155 ) );
	vecStudent.push_back( Zeng::CStudent( 165 ) );
	vecStudent.push_back( Zeng::CStudent( 175 ) );
	vecStudent.push_back( Zeng::CStudent( 185 ) );
	vecStudent.push_back( Zeng::CStudent( 195 ) );

	// use function object
	Zeng::CAverageHeight ah;
	// use function object in the stl algorithm
	ah = for_each( vecStudent.begin(), vecStudent.end(), ah);
	cout << "average height is : " << ah.GetAverageHeight() << endl;
	cout << "the student count is : " << ah.GetCount() << endl;

	return 0;
}

说明:在这里创建了一个函数对象ah并将它应用到for_each()算法中,for_each()算法会以容器中的每个Student对象为参数来对这个函数对象的"()"操作符进行调用。这时,函数对象自然就会将每个

Student对象的身高累加到它自己的m_nTotalHeight属性上,同事它还会记录已经统计过的对象数目。最后,for_each()算法会将完成统计后的函数对象作为结果返回,而这时的函数对象ah已经是一个保存了统计结果的函数对象了。通过函数对象提供的接口函数,可以轻松地获得统计结果并进行输出。


还可以这么用:

#include "stdafx.h"
#include "vector"
#include "algorithm"
#include "iostream"
using namespace std;

namespace Zeng
{
	class CStudent
	{
	public:
		CStudent( int nHeight ) : m_nHieght( nHeight ) 
		{
		}
		int GetHeight()
		{
			return m_nHieght;
		}
	private:
		int m_nHieght;
	};

	class CAverageHeight
	{
	public:
		CAverageHeight() : m_nCount( 0 ), m_nTotalHeight( 0 )
		{
		}
		void operator ()( CStudent st )
		{
			m_nTotalHeight += st.GetHeight();
			m_nCount++;
		}
		operator float()
		{
			return GetAverageHeight();
		}
		operator int()
		{
			return GetCount();
		}
		int GetCount()
		{
			return m_nCount;
		}
		int GetTotalHeight()
		{
			return m_nTotalHeight;
		}
		float GetAverageHeight()
		{
			if ( 0 != m_nCount )
			{
				return static_cast<float>( GetTotalHeight() / GetCount() );
			}
			return 0;
		}
	private:
		int m_nCount;
		int m_nTotalHeight;
	};
}


int _tmain(int argc, _TCHAR* argv[])
{
	vector<Zeng::CStudent> vecStudent;
	vecStudent.push_back( Zeng::CStudent( 155 ) );
	vecStudent.push_back( Zeng::CStudent( 165 ) );
	vecStudent.push_back( Zeng::CStudent( 175 ) );
	vecStudent.push_back( Zeng::CStudent( 185 ) );
	vecStudent.push_back( Zeng::CStudent( 195 ) );

	// use function object
	float fAverHeight = for_each( vecStudent.begin(), vecStudent.end(), Zeng::CAverageHeight() );
	cout << "average height is : " << fAverHeight << endl;
	int iCount = for_each( vecStudent.begin(), vecStudent.end(), Zeng::CAverageHeight() );
	cout << "average height is : " << iCount << endl;
	return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics