Pergunta

Eu estou trabalhando em um projeto bastante complexo, uma rotina de criptografia personalizado se você vai (apenas por diversão) e eu tenho que correr para este problema em projetar meu layout de código.

Eu tenho um número de funções que eu quero ser capaz de chamar pelo índice. Especificamente, eu preciso ser capaz de chamar um aleatoriamente para o processo de criptografar, mas depois endereço que por um índice específico no processo de descriptografar.

Eu estava pensando em uma matriz função clássica, mas a minha principal preocupação é que uma matriz função seria complicado de manter, e um pouco feio. (O objetivo é fazer com que cada par função em um arquivo separado, para reduzir os tempos de compilação e tornar o código mais fácil de gerir.) Alguém tem uma solução mais elegante C ++ como uma alternativa a uma matriz de função? A velocidade não é realmente um problema, estou mais preocupado com a manutenção.

-Nicholas

Foi útil?

Solução

Você poderia escrever algo como:

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);

Você pode usar operator() vez de Run como o nome da função, se você preferir.

Outras dicas

O que há de errado com variedade função?

Você precisa chamar funções pelo índice. Assim, eles devem ser colocados em uma estrutura "indexável pelo índice" de alguma forma . Array é provavelmente a estrutura mais simples que ternos essa necessidade.

Exemplo (digitando fora de minha cabeça, pode não compilar):

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

O que é "feio" ou "difícil de manter" na abordagem acima?

Um objeto com um método operator () definida pode agir muito como uma função, mas ser geralmente mais agradável para trabalhar.

O polimorfismo poderia fazer o truque:. Você couldf seguir o padrão de estratégia, considerando cada estratégia para implementar um de seus funções (ou um par deles)

Em seguida, crie um vetor de estratégias, e usar esta em vez da lista de funções.

Mas, francamente, eu não vejo o problema com a matriz de função; você pode facilmente criar um typedef para facilitar a legibilidade. Effectifely, você vai acabar com exatamente a mesma estrutura de arquivos ao usar o padrão de estratégia.

// 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 };
  • A declaração da função e as definições estão em arquivos separados - tempo de compilação é ok
  • .
  • O agrupamento função está em um arquivo separado, tendo uma dependência para as declarações única

Você poderia dar uma olhada na biblioteca Boost.Signals . Eu acredito que tem a capacidade de chamar suas funções registradas usando um índice.

Tente classe Loki :: Functor. Mais informações em CodeProject.com

Você precisa usar uma matriz de ponteiros de função. O único problema é que todas as funções tem que ter basicamente o mesmo protótipo, apenas o nome da função e nomes de argumentos passados ??podem variar. Os tipos tipo de retorno e argumentos (bem como o número de argumentos e ordem) devem ser idênticas.

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

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

Em seguida, você pode fazer algo como isto:

int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();

Se você olhou na biblioteca boost::signals, você verá um exemplo muito bom, que é muito elegante:
Suponha que você tem 4 funções como:

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;
}

Então, se você quiser chamá-los em uma tentativa maneira elegante:

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);

E a saída é:

The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top