欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-01-04 22:02:22
...
怎样选择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;
}


上一篇:

下一篇: