C ++函数列表

时间:2020-03-06 14:38:53  来源:igfitidea点击:

我正在一个相当复杂的项目中,如果愿意的话,将使用自定义加密例程(只是为了好玩),并且在设计代码布局时遇到了这个问题。

我想通过索引调用许多函数。具体来说,我需要能够为加密过程随机调用一个,然后在解密过程中通过特定的索引来解决这个问题。

我当时考虑的是经典的函数数组,但是我主要担心的是,函数数组的维护非常棘手,而且有些丑陋。 (目标是将每个函数对放在一个单独的文件中,以减少编译时间并使代码更易于管理。)是否有人有一个更优雅的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++]();