2

最近、独自のスクリプト言語を作成しました。私のコード構造は多態性に大きく基づいています。(これがどのように呼び出されるのかはよくわかりません。仮想関数を持っているので、クラスを派生させ、実行時に何を呼び出すかをOSに決定させます):

class Statement 
{ 
    virtual void exec() = 0; 
};

class PrintStmt : public Statement
{ 
    void exec() 
    { 
        std::cout << expression->eval(); 
    };    

class AssignStmt : public Statement
{ 
    void exec() 
    { 
        vm->bind_var(name, expression->eval()) 
    };

純粋な C コンパイラでコンパイルできるように、これを作り直す方法はありますか? これは一般的な質問であり、単一の答えがないことは承知していますが、どのように答えますか?

注: 参考までに python コードをダウンロードしましたが、それがどのように機能するかを理解するには時間がかかります。

4

2 に答える 2

3

Statementになりますstruct。そのデータ メンバーに加えて、関数ポインターが必要になります。

struct Statement
{
    void(*exec)(Statement* this); // Function pointer
    // Other members
};

次に、ステートメントタイプごとに異なる関数の実装と、適切なタイプのオブジェクトを製造するための関数を使用します。

static void printExec(struct Statement* this)
{
    printf("%s", this->whatever);
}

struct Statement* createPrintStatement()
{
    struct Statement* statement = calloc(1, sizeof(struct Statement));
    statement->exec = printExec;
    return statement;
}

そして、次のように呼び出します。

statement->exec(statement);

ポインターを使用thisすると、特定の構造体のデータ メンバー、つまり実行した exec メソッドのインスタンスにアクセスできます。

関数が多数ある場合は、vtable の使用を検討してください。

struct VTable
{
    void(*exec)(Statement* this); // Function pointer
    const char* (*stringValue)(Statement* this); // Function pointer
};

struct Statement
{
    struct VTable* vtable;
    // Other members
};

オブジェクトの種類ごとに vtable を 1 回だけ作成します

struct VTable printVTable =
{
    printExec,
    printStringValue
};

次のようにして、新しいオブジェクトを作成します。

struct Statement* createPrintStatement()
{
    struct Statement* statement = calloc(1, sizeof(struct Statement));
    statement->vtable = &printVTable;
    return statement;
}

このようにメソッドを呼び出します

statement->vtable->exec(statement);

vtable メソッドは、多かれ少なかれ C++ が舞台裏で行っていることです。

于 2013-04-19T15:58:21.290 に答える