4

我正在用 C++ 重写一个 C 程序以利用 OO 方面的优势,因此它可以轻松支持多种设备,并且程序的一部分是表达式评估器。表达式可以有函数调用,这里是函数的结构。

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找到更多信息(用于可变数量参数的函数之一)

于 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 回答
1

您可以在 C++ 中通过在参数列表中使用 ... 来执行此操作。看看这里的解释。但我认为如果你只是将参数向量传递给你的函数会更好。

于 2009-10-07T05:59:17.050 回答
0

请记住,函数只是另一个地址,在调用 start 时从堆栈中获取输入参数。所以,当你声明一个函数时,你只是存储了那个函数的地址。使用该地址,以后可以使用不同的参数调用该函数。是的,它可以通过使用参数列表在 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 回答