3

假设我有 1000 个函数定义如下

void func dummy1(int a);
void func dummy2(int a, int aa);
void func dummy3(int a, int aa, int aaa);
.
.
.
void func dummy1000(int a, int aa, int aaa, ...);

我想编写一个函数,它需要一个整数 n (n < 1000) 并根据需要调用 nth 个虚拟函数(如果是 10,则为 dummy10),并带有恰好 n 个参数(参数可以是任何整数,比如说 0)。我知道这可以通过编写一个包含 1000 个案例的 switch case 语句来实现,这是不合理的。

在我看来,如果不在运行时重新编译,这是无法实现的,所以像 java、c、c++ 这样的语言永远不会让这样的事情发生。

希望有办法做到这一点。如果是这样我很好奇。

注意:这不是我永远不会使用的东西,我只是出于好奇而提出问题。

4

5 回答 5

2

在现代函数式语言中,您可以制作一个将列表作为参数的函数列表。这可以说可以解决您的问题,但也可以说是作弊,因为它不是您的问题似乎暗示的静态类型实现。然而,当使用“手动”参数处理时,这几乎是 Python、Ruby 或 Perl 等动态语言所做的......

无论如何,以下是在 Haskell 中:它为n第 th 函数(从它的第一个参数)提供第二个参数()的副本fs列表,并返回结果。当然,您需要以某种方式将函数列表放在一起,但与 switch 语句不同,此列表将可作为一等参数重用。nx

selectApplyFunction :: [ [Int] -> a ] -> Int -> Int -> a
selectApplyFunction fs x n = (fs !! (n-1)) (replicate n x)

dummy1 [a] = 5 * a
dummy2 [a, b] = (a + 3) * b
dummy3 [a, b, c] = (a*b*c) / (a*b + b*c + c*a)
...
myFunctionList = [ dummy1, dummy2, dummy3, ... ]

-- (myfunction n) provides n copies of the number 42 to the n'th function
myFunction = selectApplyFunction myFunctionList 42

-- call the 666'th function with 666 copies of 42
result = myFunction 666

当然,如果n大于函数的数量,或者如果函数无法处理给定的列表,则会出现异常。还要注意,它是糟糕的 Haskell 风格——主要是因为它滥用列表来(滥用)解决你的问题的方式......

于 2013-02-20T22:05:21.047 回答
0

不,你不正确。大多数现代语言都支持某种形式的反射,它允许您按名称调用函数并将参数传递给它。

于 2013-02-19T21:20:35.840 回答
0

您可以使用大多数现代语言创建一系列函数。在伪代码中,

var dummy = new Array();
dummy[1] = function(int a);
dummy[2] = function(int a, int aa);
...

var result = dummy[whateveryoucall](1,2,3,...,whateveryoucall);
于 2013-02-19T21:22:02.447 回答
0

在函数式语言中,你可以做这样的事情,在强类型语言中,比如 Haskell,函数必须具有相同的类型,但是:

funs = [reverse, tail, init]   -- 3 functions of type [a]->[a]

run fn arg = (funs !! fn) $ args  -- applies function at index fn to args
于 2013-02-20T10:53:26.290 回答
0

在面向对象的语言中,您可以一起使用函数对象和反射来实现您想要的。通过将适当的 POJO(调用 C 结构)传递给函数对象来解决参数数量可变的问题。

interface Functor<A,B> {
    public B compute(A input);
}

class SumInput {
    private int x, y;
    // getters and setters
}

class Sum implements Functor<SumInput, Integer> {

    @Override
    public Integer compute(SumInput input) {
       return input.getX() + input.getY();
    }

}

现在想象你有大量的这些“函子”。您将它们收集在一个配置文件中(可能是一个 XML 文件,其中包含有关每个仿函数、使用场景、说明等的元数据)并将列表返回给用户。
用户选择其中之一。通过使用反射,您可以看到所需的输入和预期的输出。用户填写输入,并通过使用反射实例化函子类(newInstance()),调用compute()函数并获得输出。
当你添加一个新的仿函数时,你只需要改变配置文件中的仿函数列表。

于 2013-02-20T11:06:07.247 回答