4

オブジェクト指向の側面を利用して複数のデバイスを簡単にサポートできるように、C++ で C プログラムを書き直す作業を行っています。プログラムの一部は式評価器です。式には関数呼び出しを含めることができます。関数の構造は次のとおりです。

typedef struct {
    char *name;
    int argc;
    void (*func) ();
} FUNCTION;

どういうわけか、 func は可変数の引数を渡すことができます。

RESULT *param[10];

if (Root->Function->argc < 0) {
    /* Function with variable argument list:  */
    /* pass number of arguments as first parameter */
    Root->Function->func(Root->Result, argc, &param);
} else {
    Root->Function->func(Root->Result, param[0], param[1], param[2], param[3], param[4], param[5], param[6],
                         param[7], param[8], param[9]);
}

正直なところ、これがCでどのように行われるのかさえわかりません。説明は素晴らしいでしょう。C++でできますか?

4

5 に答える 5

8

var argsは、探しているものです。C と C++ の両方で動作します。これはprintf()、たとえば :) に使用されるものです。

va_arg (可変数の引数に使用される関数の 1 つ) をグーグルで検索すると、より多くの情報を見つけることができます。

于 2009-10-07T05:55:59.023 に答える
6

実際、私はここにいるすべての人、そしてあなたの望みに逆らいます。

省略記号が間違っています。それは C では不可欠なものと考えられていましたが、それ以来、私たちはよりよく学びました。

実際、オブジェクトや関数オブジェクトなどを使用して、実際に C++ をより良くする方法があります。

あなたが探しているのはCommand Patternです。

「Command」という基本クラス (execute() メソッドとのインターフェース) を作成し、「void (*func)()」に入れたい「関数」ごとに派生クラスを作成します。

これで、コードは次のようになります。

std::vector<RESULT*> param(10, NULL);

if (Root->Function->argc < 0) {
    /* Function with variable argument list:  */
    /* pass number of arguments as first parameter */
    Command1* aCommand = new Command1(Root->Result);
    aCommand->set(Root->Result, argc, &param);
    Root->Function->command = aCommand;
    Root->Function->command->execute();
} else {
    Command2* aCommand = new Command2(Root->Result);
    aCommand->set(Root->Result, param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], param[8], param[9]);
    Root->Function->command = aCommand;
    Root->Function->command->execute();
}

ここでは省略記号は必要ありません。各コマンド オブジェクトは特殊化されており、必要なパラメーター (数と型) が正確にわかっているからです。

コマンド パターンを使用すると、'...' (省略記号) のすべての利点を不便なく利用できます。もちろん、とにかく間違いを犯さないので時間の無駄だと言う人もいます... 残念ながら、私はそれほど頭が良くないので、制約 (数値、型) を定義することを好みます、アサーション) をコンパイラに強制させます。

于 2009-10-07T06:46:38.187 に答える
0

関数は単なる別のアドレスであり、start が呼び出されたときにスタックから入力パラメーターを取得することを忘れないでください。したがって、FUNCTION を宣言するときは、その関数のアドレスを格納しているだけです。そのアドレスを使用すると、後で異なるパラメーターを使用して関数を呼び出すことができます。はい、引数リストを使用して C++ で実行できますが、実装はそれをどのように処理するかによって異なります。

于 2009-10-07T06:00:04.833 に答える
0

個人的には、式の AST を評価する場合、ドメイン固有言語を使用して AST ノード構造体の階層構造と一連の複数ディスパッチ操作を生成する傾向があります。私はこれのための独自の DSL を持っていますが、そのアイデアはtreeccから盗まれました。単一のノード クラスや単一の評価ノード関数を使用する必要がないため、多くの問題が解消されます。また、DSL がさまざまなチェックを行うため、これらの問題を別の問題に置き換えることをほとんど回避できます。

treecc は、C または C++ 出力 (または他のいくつかの言語) IIRC を生成できます。flex や bison を使用するのとよく似ています。生成されたコードは少し素朴で、すぐに継承をもっと制御したいと思うようになりますが、うまく機能します。

于 2009-10-07T07:41:14.600 に答える