2015-09-27 183 views
10

我想给一个函数指针分配一个函数的地址,但是要处理的函数返回一个函数指针,它与自身的签名相同,导致它的递归方式我根本不能写返回类型,对于函数指针,甚至在函数声明本身......如何写一个函数指针返回一个函数指针函数?

我想简化问题的一种方式,所以它不是混乱:

我怎么能写一个函数声明例如,它可以返回一个指针本身(或具有相同签名的任何其他功能)?

????? function(int a){ 
    // could be this function, or another with the same signature, 
    return arbitraryFunction; 
} 

?????(*func)(int) = function; // same problem as above 

编辑:

现在我有一个解决方案,但我不会发布它作为一个答案,因为它是积极难看。它得到通过返回原始void*指针作为返回类型摆脱递归的,并最终采取以下形式:

void* function(int parameter){ 
    return arbitraryFunction; // of the same signature 
} 

void*(*func)(int) = function; 
func = reinterpret_cast<void*(*)(int)>(func(42)); // sin 

EDIT2:

似乎函数指针和普通指针之间铸造是UB,所以我不能在这种情况下使用void* ...

要回答其中一个注释,这是为了在我的程序中的多个“主”循环之间传递控制,每个循环获取它自己的函数。有很多方法可以做到这一点,但返回函数指针(或NULL来终止程序)中间循环似乎像最简单的方法,但我没有预料到指向数据和指向函数地址的指针将是不可兼容的与彼此。我认为在这种情况下返回多态函数对象最终会成为更理智的选择。

+1

我想你不能这样做,至少不容易。 –

+0

我不知道是否返回'void *'作为函数和函数指针的返回类型,可以让我避免递归声明... –

+0

顺便说一句,即使Ocaml不允许这样做,除非您用'-ypeypes'调用'ocamlc'(for *递归类型*) –

回答

6

请勿使用void*,因为不能保证void *可以容纳函数指针。可以使用void(*)()作为一种解决方法:

typedef void(*void_func)(); 
typedef void_func (*func_type) (int); 
void_func arbitraryFunction(int a) { 
    // could be this function, or another with the same signature, 
    cout << "arbitraryFunction\n"; 
    return nullptr; 
} 
void_func function(int a) { 
    // could be this function, or another with the same signature, 
    return (void_func) arbitraryFunction; 
} 
int main() { 
    // your code goes here 
    func_type f = (func_type) function(0); 
    f(0); 
    return 0; 
} 

LIVE

C99 [6.2.5/27]:

作废应具有相同的表示和对齐要求作为指针的指针到一个字符类型。同样,指向 兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。所有指向 结构类型的指针都应具有相同的表示形式和对齐要求。所有指向联合类型的指针应具有相同的表示和对齐要求。其他类型的指针 不需要具有相同的表示或对齐 的要求。

C99 [6.3.2。3/8]:

指向一种类型的函数的指针可能会转换为指向另一种类型的函数的指针并返回;结果应该比较 等于原始指针。

+2

虽然它不能返回void,因为'func'需要匹配返回它的函数,它返回'func' –

+1

请注意,将函数指针转换为'void *'是UB,并且不需要支持也不会在来回转换时保留其价值。 – edmz

+1

@PiotrSkotnicki我修复了我的答案。 – songyuanyao

5

C中的关键是要利用这一事实,任何一种函数指针都可以转换为任何其他类型的函数指针的优势:

#include <stdlib.h> 
#include <stdio.h> 

typedef void(*emptyfunc)(void); 
typedef emptyfunc (*funcptr2)(int); 

funcptr2 strategy(int m) 
{ 
    printf("Strategy %d.\n", m); 
    return (funcptr2)&strategy; 
} 

int main (void) 
{ 
    const funcptr2 strategy2 = (funcptr2)strategy(1); 
    const funcptr2 strategy3 = (funcptr2)strategy2(2); 
    strategy3(3); 

    return EXIT_SUCCESS; 
} 

每个指针的战略始终处于可以调用一次的类型,并将返回值放回到可以再次调用的表单中。

在C++中,你将宣布一个函数对象:

class strategy { 
    public: 
    virtual const strategy& operator()(int) const = 0; 
} 

这个类的一个实例可以这样调用一个函数。

+0

如何从成员函数返回其他函数对象的引用? – songyuanyao

+0

@songyuanyao我不确定我是否理解这个问题,但其中一种方法是将策略制作为抽象基类,并具有实现不同策略的子类。然后你可以返回这些实例。 – Davislor

+0

我的意思是在其中一个子类中,当你返回另一个子类时,你必须保持引用有效,通过使用全局变量等。 – songyuanyao

1

我怀疑你正在尝试做的是一些更复杂的版本是这样的:

typedef MainLoop *MainLoop(); // not legal 

extern MainLoop* main_loop_1(); 
extern MainLoop* main_loop_2(); 

MainLoop* main_loop_1() 
{ 
    // do some work here 
    return main_loop_2; 
} 

MainLoop* main_loop_2() 
{ 
    // do some work here 
    return main_loop_1; 
} 

int main() 
{ 
    MainLoop f = main_loop_1; 

    for (;;) { 
     f = f(); 
    } 
} 

一个解决办法是包装在一个结构中的函数指针:

struct MainLoop { 
    MainLoop (*function_ptr)(); // legal 
}; 

extern MainLoop main_loop_1(); 
extern MainLoop main_loop_2(); 

MainLoop main_loop_1() 
{ 
    // do some work here 
    return {main_loop_2}; 
} 

MainLoop main_loop_2() 
{ 
    // do some work here 
    return {main_loop_1}; 
} 

int main() 
{ 
    MainLoop f{main_loop_1}; 

    for (;;) { 
     f = f.function_ptr(); 
    } 
} 
+0

问题中的问题是声明一个链表的函数指针模拟,这个答案就是你在这两种情况下的做法。 – PBS