1

私はかなり複雑なプロジェクト、カスタム暗号化ルーチンに取り組んでいます (楽しみのために)。コード レイアウトを設計する際にこの問題に遭遇しました。

インデックスで呼び出せるようにしたい関数がいくつかあります。具体的には、暗号化プロセスのためにランダムに呼び出すことができる必要がありますが、復号化プロセスでは特定のインデックスによってそれに対処します。

私は古典的な関数配列を検討していましたが、私の主な懸念は、関数配列は維持するのが難しく、少し醜いということです。(目標は、コンパイル時間を短縮し、コードを管理しやすくするために、各関数ペアを個別のファイルに入れることです。) 関数配列の代わりとして、より洗練された C++ ソリューションを持っている人はいますか? 速度はそれほど問題ではありませんが、保守性が心配です。

-ニコラス

4

8 に答える 8

5

関数配列の何が問題になっていますか?

インデックスで関数を呼び出す必要があります。したがって、それらは何らかの形で「インデックスによるインデックス付け可能」構造に入れられる必要があります。配列は、おそらくこのニーズに合った最も単純な構造です。

例(頭から入力すると、コンパイルされない可能性があります):

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

上記のアプローチで「醜い」または「維持するのが難しい」とは何ですか?

于 2008-09-24T07:52:52.773 に答える
2

次のように書くことができます。

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関数名として使用できます。

于 2008-09-24T08:00:09.760 に答える
0

operator()メソッドが定義されたオブジェクトは、関数のように機能しますが、一般的に操作が簡単です。

于 2008-09-24T07:50:35.460 に答える
0

ライブラリを見る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
于 2008-09-24T09:39:00.647 に答える
0

Boost.Signals ライブラリをご覧ください。インデックスを使用して登録済みの関数を呼び出す機能があると思います。

于 2008-09-24T08:15:13.997 に答える
0

関数ポインターの配列を使用する必要があります。唯一の問題は、すべての関数が基本的に同じプロトタイプを持つ必要があり、関数の名前と渡された引数の名前だけが異なる可能性があることです。戻り値の型と引数の型 (および引数の数と順序) は同一でなければなりません。

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

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

次に、次のようなことができます。

int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();
于 2010-06-24T15:58:14.460 に答える
0

Loki::Functor クラスを試してみてください。詳細はCodeProject.comをご覧ください

于 2008-09-24T08:30:07.037 に答える
0

ポリモーフィズムはトリックを行うことができます: 戦略パターンに従って、各戦略が関数の 1 つ (またはそれらのペア) を実装することを検討します。

次に、戦略のベクトルを作成し、関数リストの代わりにこれを使用します。

しかし、率直に言って、関数配列の問題はわかりません。読みやすくするために、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 };
  • 関数の宣言と定義は別のファイルにあります - コンパイル時間は問題ありません。
  • 関数のグループ化は別のファイルにあり、宣言のみに依存します
于 2008-09-24T08:05:11.137 に答える