题目:创建一个函数对象,检查一个人、一辆汽车或一条狗的年龄大于限定值的个数。
此对象,我们定义为 older_than,这是一个类对象。
方法一:面向对象
创建一个包含 age()虚函数的超类。
class Object
{
public:
virtual int age() = 0;
};
class A:public Object
{
public:
int age(){return 21;}
};
class B:public Object
{
public:
int age(){return 11;}
};
class older_than
{
public:
bool operator()(Object* object){
return object->age() > m_limit;
}
private:
int m_limit = 12;
};
std::count_if(persons.cbegin(), persons.cend(), older_than(new A()));
std::count_if(cars.cbegin(), cars.cend(), older_than(new B()));
但是:这种方法会影响运行时的性能,而且对与支持 older_than函数对象的所有类都必须强制继承这个超类,破坏了封装性。
方法二:类模板
将 older_than类改造成类模板,对于需要检测年龄的类型创建模板类。
template<typename T>
class older_than
{
public:
older_than(int limit):m_limit(limit){}
bool operator()(const T& object) const{
return object.age() > m_limit;
}
private:
int m_limit;
};
//对于具有 .age() get方法的任意类型都可以使用 older_than
std::count_if(persons.cbegin(), persons.cend(), older_than<person_t>(42));
std::count_if(cars.cbegin(), cars.cend(), older_than<cars_t>(42));
std::count_if(dogs.cbegin(), dogs.cend(), older_than<dogs_t>(42));
但是:这种方法在实例化的时候要检测对象,必须指定对象的类型,很可能导致指定的类型与调用操作符要求的类型不一致的问题。
方法三:模板成员函数
因此,可以把调用操作符合作为一个模板成员函数,而不是创建一个模板,这种情况在实例化 older_than函数对象时,就不需要指定类型,编译器在调用“调用操作符”时,会自动推测参数的类型。
template<typename T>
class older_than
{
public:
older_than(int limit):m_limit(limit){}
template<typename T>
bool operator()( T&& object) const{
//age成员函数有不同的重载 左值和右值,可调用正确重载
return std::forward<T>(object).age() > m_limit;
}
private:
int m_limit;
};
//再使用 older_than函数对象时,就不用显式指明对象类型了,甚至可以对不同的类型使用相同的对象示例
older_than pp(5);
std::count_if(persons.cbegin(), persons.cend(), pp);
std::count_if(cars.cbegin(), cars.cend(), pp);
std::count_if(dogs.cbegin(), dogs.cend(), pp);
认识一个人就是开了一扇窗户,就能看到不一样的东西,听到不一样的声音,能让你思考,觉悟,这已经够了。其他还有很多,比如机会,帮助,我不确定。这个在一般人看来可能不重要,但是我知道这个很重要。