假如,现在有个类,它含有数据,我们需要为它编写一些遍历的函数。
就比如,类是这样的:
class SomeClass
{
enum{ Length = 512};
int element[Length];
public:
void traver()
{
//做一些遍历
}
};
那如果有需求,要求遍历函数能够依据不同的情况,采取不同的遍历函数,怎么办呢?
可以让SomeClass 包含一个函数指针,通过函数指针调用函数进行遍历,还可以通过修改函数指针的值,以产生不同的遍历行为。
这个代码就不写了。但是这样有个明显的问题,如果我在函数中,还需要额外的参数呢?那怎么办?
我们可以额外声明一个抽象类,提供接口用于编写遍历函数
class DoFunc
{
public:
virtual ~DoFunc() {}
virtual void func(int&) = 0;
};
class Increase: public DoFunc
{
public:
void func(int& i)
{
++i;
}
};
class Decrease: public DoFunc
{
public:
void func(int& i)
{
--i;
}
};
class SomeClass
{
enum{ Length = 512};
int element[Length];
DoFunc* dofunc;
public:
SomeClass(DoFunc* indo): dofunc(indo) {}
void traver()
{
for(int i=0;i<Length;++i)
dofunc->func(element[i]);
}
void setFunc(DoFunc* indo)
{
dofunc = indo;
}
};
那么,对于使用这样:
Increase in;
Decrease de;
SomeClass s(&in);
//...
s.setFunc(&de);
这是一种不错的设计方案:
至于参数,只要让DoFunc 的derived class 拥有就可以了。
除此之外,我们还可以使用模板
class Increase
{
public:
void operator () (int& i)
{
++i;
}
};
class Decrease
{
public:
void operator () (int& i)
{
--i;
}
};
class SomeClass
{
enum{ Length = 512};
int element[Length];
public:
SomeClass(){}
template<typename T>
void traver(T t)
{
for(int i=0;i<Length;++i)
t(element[i]);
}
};
模板能够接受的参数很多,函数指针,重载了() 操作符的类,lambda 表达式等。
那么使用可以如下:
Increase in;
Decrease de;
SomeClass s;
s.traver(in);
s.traver(de);
s.traver([](int& i) -> void
{
i += 10;
});
[参考资料]
[1] Scott Meyers 著, 侯捷译. Effective C++ 中文版: 改善程序技术与设计思维的 55 个有效做法[M]. 电子工业出版社, 2011.
(条款35:考虑virtual 函数以外的选择)