C ++函数列表
我正在一个相当复杂的项目中,如果愿意的话,将使用自定义加密例程(只是为了好玩),并且在设计代码布局时遇到了这个问题。
我想通过索引调用许多函数。具体来说,我需要能够为加密过程随机调用一个,然后在解密过程中通过特定的索引来解决这个问题。
我当时考虑的是经典的函数数组,但是我主要担心的是,函数数组的维护非常棘手,而且有些丑陋。 (目标是将每个函数对放在一个单独的文件中,以减少编译时间并使代码更易于管理。)是否有人有一个更优雅的C ++解决方案来替代函数数组?速度并不是真正的问题,我更担心可维护性。
-尼古拉斯
解决方案
定义了operator()方法的对象可以像函数一样工作,但通常更好用。
函数数组有什么问题?
我们需要按索引调用函数。因此,必须以某种方式将它们置于"按索引可索引"的结构中。数组可能是满足此需求的最简单的结构。
示例(在我脑海中打字,可能无法编译):
struct FunctionPair { EncodeFunction encode; DecodeFunction decode; }; FunctionPair g_Functions[] = { { MyEncode1, MyDecode1 }, { MySuperEncode, MySuperDecode }, { MyTurboEncode, MyTurboDecode }, };
在上面的方法中,"丑陋"或者"难以维护"是什么?
我们可以这样写:
class EncryptionFunction { public: virtual Foo Run(Bar input) = 0; virtual ~MyFunction() {} }; class SomeSpecificEncryptionFunction : public EncryptionFunction { // override the Run function }; // ... std::vector<EncryptionFunction*> functions; // ... functions[2]->Run(data);
如果愿意,可以使用operator()
代替Run
作为函数名。
多态可以解决问题:我们可以遵循策略模式,考虑每种策略来实现一个功能(或者一对功能)。
然后创建一个策略向量,并使用它代替功能列表。
但坦率地说,我看不到函数数组有问题。我们可以轻松创建typedef以简化可读性。实际上,使用策略模式时,最终将获得完全相同的文件结构。
// functiontype.h typedef bool (*forwardfunction)( double*, double* ); // f1.h #include "functiontype.h" bool f1( double*, double* ); // f1.c #include "functiontype.h" #include "f1.h" bool f1( double* p1, double* p2 ) { return false; } // functioncontainer.c #include "functiontype.h" #include "f1.h" #include "f2.h" #include "f3.h" forwardfunction my_functions[] = { f1, f2, f3 };
- 函数的声明和定义在单独的文件中-编译时间可以。
- 函数分组在单独的文件中,仅依赖于声明
我们可以看一下Boost.Signals库。我相信它具有使用索引调用其注册函数的能力。
尝试Loki :: Functor类。有关更多信息,请访问CodeProject.com
如果我们在boost :: signals
库中查看,我们会看到一个非常漂亮的示例,它非常优雅:
假设我们有4个功能,例如:
void print_sum(float x, float y) { std::cout << "The sum is " << x+y << std::endl; } void print_product(float x, float y) { std::cout << "The product is " << x*y << std::endl; } void print_difference(float x, float y) { std::cout << "The difference is " << x-y << std::endl; } void print_quotient(float x, float y) { std::cout << "The quotient is " << x/y << std::endl; }
然后,如果我们想以一种优雅的方式调用它们,请尝试:
boost::signal<void (float, float)> sig; sig.connect(&print_sum); sig.connect(&print_product); sig.connect(&print_difference); sig.connect(&print_quotient); sig(5, 3);
输出为:
The sum is 8 The product is 15 The difference is 2 The quotient is 1.66667
我们需要使用函数指针数组。唯一的问题是所有功能必须具有基本相同的原型,只有功能名称和传递的参数名称可以不同。返回类型和参数类型(以及参数和顺序的数量)必须相同。
int Proto1( void ); int Proto2( void ); int Proto3( void ); int (*functinPointer[3])( void ) = { Proto1, Proto2, Proto3 };
然后,我们可以执行以下操作:
int iFuncIdx = 0; int iRetCode = functinPointer[iFuncIdx++]();