Список функций C ++ - PullRequest
       11

Список функций C ++

1 голос
/ 24 сентября 2008

Я работаю над довольно сложным проектом, по вашему желанию, собственной процедурой шифрования (просто для удовольствия), и я столкнулся с этой проблемой при разработке макета кода.

У меня есть ряд функций, которые я хочу вызывать по индексу. В частности, мне нужно иметь возможность вызывать один случайным образом для процесса шифрования, но затем обращаться к нему по определенному индексу в процессе расшифровки.

Я думал о классическом функциональном массиве, но моя главная проблема в том, что функциональный массив будет сложно поддерживать и немного уродлив. (Цель состоит в том, чтобы собрать каждую пару функций в отдельный файл, сократить время компиляции и упростить управление кодом.) Есть ли у кого-нибудь более элегантное решение C ++ в качестве альтернативы массиву функций? Скорость на самом деле не проблема, меня больше беспокоит ремонтопригодность.

-Nicholas

Ответы [ 8 ]

5 голосов
/ 24 сентября 2008

Что не так с массивом функций?

Вам нужно вызывать функции по индексу. Таким образом, они должны быть помещены в некую структуру «индексируемую по индексу» каким-то образом . Массив, вероятно, является самой простой структурой, которая удовлетворяет этой потребности.

Пример (печатать у меня в голове, может не скомпилироваться):

struct FunctionPair {
   EncodeFunction encode;
   DecodeFunction decode;
};
FunctionPair g_Functions[] = {
   { MyEncode1, MyDecode1 },
   { MySuperEncode, MySuperDecode },
   { MyTurboEncode, MyTurboDecode },
};

Что такое "некрасиво" или "трудно поддерживать" в подходе выше?

2 голосов
/ 24 сентября 2008

Вы можете написать что-то вроде:

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 в качестве имени функции, если хотите.

0 голосов
/ 24 июня 2010

Вам нужно использовать массив указателей на функции. Единственный улов заключается в том, что все функции должны иметь в основном один и тот же прототип, могут варьироваться только имя функции и имена переданных аргументов. Тип возвращаемого значения и типы аргументов (а также количество аргументов и порядок) должны быть идентичны.

int Proto1( void );
int Proto2( void );
int Proto3( void );

int (*functinPointer[3])( void ) =
{
   Proto1,
   Proto2,
   Proto3
};

Тогда вы можете сделать что-то вроде этого:

int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();
0 голосов
/ 24 сентября 2008

Если вы заглянули в библиотеку 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
0 голосов
/ 24 сентября 2008

Попробуйте класс Loki :: Functor. Больше информации на CodeProject.com

0 голосов
/ 24 сентября 2008

Вы можете взглянуть на библиотеку Boost.Signals . Я считаю, что он имеет возможность вызывать свои зарегистрированные функции, используя индекс.

0 голосов
/ 24 сентября 2008

Полиморфизм может помочь: вы можете следовать шаблону стратегии, рассматривая каждую стратегию для реализации одной из ваших функций (или пары из них).

Затем создайте вектор стратегий и используйте его вместо списка функций.

Но, честно говоря, я не вижу проблемы с массивом функций; Вы можете легко создать 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 };
  • Объявление функции и определения находятся в отдельных файлах - время компиляции в порядке.
  • Группировка функций находится в отдельном файле, зависящем только от объявлений
0 голосов
/ 24 сентября 2008

Объект с определенным методом operator () может вести себя как функция, но в целом работать с ним приятнее.

...