我正在做一个相当复杂的项目,如果你愿意的话,一个自定义加密例程(只是为了好玩)我在设计我的代码布局时遇到了这个问题。
我有许多我希望能够按索引调用的函数。具体来说,我需要能够为加密过程随机调用一个,然后通过解密过程中的特定索引来解决它。
我正在考虑一个经典的函数数组,但我主要担心的是函数数组很难维护,而且有点难看。(目标是将每个函数对放在一个单独的文件中,以减少编译时间并使代码更易于管理。)有没有人有更优雅的 C++ 解决方案来替代函数数组?速度不是真正的问题,我更担心可维护性。
-尼古拉斯
我正在做一个相当复杂的项目,如果你愿意的话,一个自定义加密例程(只是为了好玩)我在设计我的代码布局时遇到了这个问题。
我有许多我希望能够按索引调用的函数。具体来说,我需要能够为加密过程随机调用一个,然后通过解密过程中的特定索引来解决它。
我正在考虑一个经典的函数数组,但我主要担心的是函数数组很难维护,而且有点难看。(目标是将每个函数对放在一个单独的文件中,以减少编译时间并使代码更易于管理。)有没有人有更优雅的 C++ 解决方案来替代函数数组?速度不是真正的问题,我更担心可维护性。
-尼古拉斯
函数数组有什么问题?
您需要按索引调用函数。因此,它们必须以某种方式放入某种“可按索引索引”的结构中。数组可能是最适合这种需求的最简单的结构。
示例(从我的脑海中输入,可能无法编译):
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作为函数名称。
定义了 operator() 方法的对象可以像函数一样工作,但通常更易于使用。
多态可以解决问题:您可以遵循策略模式,考虑每个策略来实现您的一个功能(或其中一对)。
然后创建一个策略向量,并使用这个而不是函数列表。
但坦率地说,我没有看到函数数组的问题。您可以轻松创建 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++]();