函数对象(仿函数)实现多态
方法:
1- 把仿函数类的数据和/或多态移到另一个类中。
2-然后给你的仿函数一个指向这个新类的指针。例子:函数对象中的虚函数会出现分割问题(因为STL的函数对象作为参数/返回值时是通过值传递的)
template<typenameT>
class BPFC: // BPFC =“Big Polymorphic
public // FunctorClass”
unary_function<T,void> {
private:
Widget w; // 这个类有很多数据,
Int x; // 所以用值传递
... // 会影响效率
public:
virtual voidoperator()(const T& val) const; // 这是一个虚函数,
... // 所以切割时会出问题
改为桥接模式实现:1,把所有数据和虚函数放到实现类
2,建立一个包含一个指向实现类的指针的小而单态的类
template<typename T> // 用于修改的BPFC
class BPFCImpl
public unary_function<T, void> { // 的新实现类
private:
Widget w; // 以前在BPFC里的所有数据
int x; // 现在在这里
...
virtual ~BPFCImpl(); // 多态类需要
// 虚析构函数
virtual void operator()(const T& val) const;
friend classBPFC<T>; // 让BPFC可以访问这些数据
};
template<typename T>
class BPFC: // 小的,单态版的BPFC
public unary_function<T, void> {
private:
BPFCImpl<T>*pImpl; // 这是BPFC唯一的数据
public:
void operator()(const T& val) const // 现在非虚;
{ // 调用BPFCImpl的
pImpl->operator()(val);
}
...
};
BPFC::operator()的实现例证了BPFC所有的虚函数是怎么实现的:它们调用了在BPFCImpl中它们真的虚函数。
结果是仿函数类(BPFC)是小而单态的,但可以访问大量状态而且行为多态------Bridge模式/Pimpl惯用法(设计模式)
注意:
必须保证BPFC的拷贝构造函数对指向的BPFCImpl对象做了合理的事情;
或者将指向的BPFCImpl对象的指针放入shared_ptr中。