標籤:
1、考慮下面的需求,從集合中找到一個與當前Student相等的學生,如下:
int main(int argc, char* argv[])
{
Student s1(20,"Andy");
Student s2(23,"Bill");
Student s3(28,"Caroline");
Student s4(27,"David");
Student s5(21,"Eric");
vector<Student> stuVec;
stuVec.push_back(s1);
stuVec.push_back(s2);
stuVec.push_back(s3);
stuVec.push_back(s4);
stuVec.push_back(s5);
Student target(23,"Bill");
vector<Student>::iterator iter = find(stuVec.begin(),stuVec.end(),target);
return 0;
}
注意:調用find方法,Student要重載成員操作符==,或者重載普通操作符==,因為find使用==比較兩個對象是否相等。
2、需求變更,找出一個年齡比target大的學生,怎麼辦?
使用函數對象,函數對象有一個成員_stu,使用target初始化_stu,重載(),比較target與序列中的每個對象
class Finder
{
public:
Finder(const Student& stu):_stu(stu)
{
}
bool operator()(const Student& rhs)
{
if(rhs._Age>_stu._Age)
{
return true;
}
return false;
}
private:
Student _stu;
};
iter = find_if(stuVec.begin(),stuVec.end(),Finder(target));
註:假如對於teacher的集合,也要同樣的需求,找出一個年齡比target大的教師,可以將Finder修改成模板類。
3、有沒有其他的辦法呢?
使用greater<Student>可以比較Student的大小,一個是變數,一個是參照物,而find_if的第三個參數,隱式介面是 Pred(*First),只接受一個參數。
使用bind2nd 對greater<Student>和參照物封裝,對外暴露介面接受一個參數,對內調用greater(參數,參照物),greater使用>比較大小,對Student進行>操作符過載。
bool operator>(const Student& lhs,const Student& rhs)
{
return lhs._Age > rhs._Age;
}
iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(greater<Student>(),target));
4、其他辦法呢?
不過載操作符,偏特化一個greater,用於比較age大小。如下:
template <>
struct greater<Student>: public binary_function<Student, Student, bool>
{
bool operator()(const Student& _Left, const Student& _Right) const
{
return (_Left._Age > _Right._Age);
}
};
iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(greater<Student>(),target));
5、因為偏特化只有一個,能不能自己寫一個類似greater的方法對象呢,並且是可以使用bind2nd適配的。
注意:為了可適配,需要繼承 public binary_function<Student, Student, bool>
struct StudentNameCompare: public binary_function<Student, Student, bool>
{
bool operator()(const Student& _Left, const Student& _Right) const
{
return (_Left._Age > _Right._Age);
}
};
iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(StudentNameCompare(),target));
當然也可以使用模板,如下:
template <typename T>
struct StudentNameCompare: public binary_function<T, T, bool>
{
bool operator()(const T& _Left, const T& _Right) const
{
return (_Left._Age > _Right._Age);
}
};
iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(StudentNameCompare<Student>(),target));
6、現在分析2的方法和5的方法,最終的介面都要滿足 Pred(*First),只接受一個參數。二者的處理策略不同。 在2中,函數對象,只接受一個參數,但是有一個欄位,這個欄位用於儲存參照物。在5中,函數對象接受兩個參數,繼承binary_function,使之可適配,然後使用bind2nd 將函數對象和參照物封裝起來,對外暴露介面只接受一個參數。
7、考慮下面的需求,找出一個年齡比target小的學生,對於5,只需要使用not1再次適配一下即可,如下:
iter = find_if(stuVec.begin(),stuVec.end(),not1(bind2nd(StudentNameCompare<Student>(),target)));
但是對於2,不行。因為2不是可適配的,要讓2是可適配的,需要繼承 public unary_function<Student,bool>,如下:
class Finder:public unary_function<Student,bool>
{
public:
Finder(const Student& stu):_stu(stu)
{
}
bool operator()(const Student& rhs) const
{
if(rhs._Age>_stu._Age)
{
return true;
}
return false;
}
private:
Student _stu;
};
當然,也可以使用模板。
C++ 函數對象