如何在不同的类中使用函数指针?

时间:2012-04-16 02:16:53

标签: c++ function-pointers

在function.h文件中,我已将函数声明为内联函数,例如

inline double foo(int &a)
{

     return a*double value
}

在a.cpp文件中,我已经包含了function.h文件并在很多地方调用了foo函数。 a.cpp文件也有一个b类实例,我想在b实例中调用foo函数。当我在b中调用一个函数时,我想将函数指针传递给b,这样我就可以在b中调用foo函数而不包含function.h文件。

b.cpp file
void b_foo(a function pointer to foo function)
{
     call foo
}

由于我已将该函数声明为内联,因此我不确定传递函数指针是否有效而不是仅仅包含b.cpp中的function.h文件。

我想看看会有什么不同。

4 个答案:

答案 0 :(得分:1)

试试这个:

typedef double (*foo_ptr)(int &);

void b_foo(foo_ptr f)
{
  if (f != NULL) {
    double d = f(5);
  }
}

void f() {
  b_foo(foo);
}

typedef可以更容易地引用指向函数的指针类型。

调用时不需要取消引用指针(可以,但没有必要)。作为参数传递时,您也不需要获取函数的地址(再次,您可以,如果需要)

请注意

inline double foo(int &a)  
{  
  return a*double value  
}

无效,因为它有语法错误。试试:

inline double foo(int &a)  
{  
  return a*4.5; 
}

你也可以声明/使用double局部变量而不是双字面

注意:您正在讨论实例中的函数。如果您确实想要调用成员函数,则需要:

typedef double (*B::foo_ptr)(int &);

其中B是声明函数的类。然后以这种方式使用它:

B b;
foo_ptr f = B::foo;
b.*f(5);

答案 1 :(得分:1)

首先,你不是用C编程的。你是用C ++编程的。这是一种不同的语言。 C没有引用或类。在你的代码中,你没有使用类,但你正在使用引用(无缘无故)。

其次,考虑“函数指针”的含义。它是该函数的代码的地址。现在考虑“内联”的含义。这意味着该功能在机器代码中不是独立存在的。它的源(概念上)放在它被调用的地方,并且编译调用函数。所以你想要获取不存在的东西的地址。

简短的回答是你不能。

你想要达到什么目的?你想永远从b打电话给foo吗?如果是这样,您不需要间接。您可以调用内联函数并将其内联到调用站点,或者您可以调用非内联函数并生成实际函数调用。

// a.c
double foo(int a) { return a * 3.1415926; }

// b.c
double foo(int a); // declaration, not definition.
void b(void) { printf("%f\n", foo(10)); }
int main() { b(); return 0; }

构建: gcc -O2 -c -o a.o a.c

请注意,在编译b.c时,编译器不知道foo的功能,它只知道它的签名。 gcc -O2 -c -o b.o b.c

这将两个部分链接到一个程序中,并在开头和结尾添加部件,以便运行它: gcc -o program a.o b.o

不同之处在于效率。内联允许许多优化(直到使用参数的值来预先计算结果并完全消除代码,就像这里一样)。内联这种优化的地方仍然可以更快,因为它消除了函数调用开销,并且可以允许更好的寄存器分配,以及使代码更有可能在缓存中。但是内联可能很糟糕,因为它会导致代码膨胀和缓存污染,使得代码不太可能在缓存中。

如果您在编译时不知道要从b调用哪个函数,则需要间接。因此,您将拥有foo_1和foo_2,并且您将传递给指向其中一个的指针,并且它将调用该指针指向的函数,而不知道它是哪一个。这有性能损失,但有时是必要的。

double foo_1(int a) { return a * 3.1415926; }
double foo_2(int a) { return a * 2.81; }

void b(double (*foo)(int)) { printf("%f\n", foo(10)); }
int main(int argc, char *argv[])
{
  if (argc < 2) return;
  b(argv[1][0]-48 ? &foo_1 : &foo_2);
  return 0;
}

C ++有一个功能,您可以告诉编译器从相同的源代码生成两个版本的函数b:一个始终调用foo_1,另一个始终调用foo_2。然后可以在两个调用站点内联foo_1和foo_2,而不是选择将指针传递给foo_1或foo_2到b,您需要选择调用b_with_foo_1或b_with_foo_2。

答案 2 :(得分:0)

点击here“功能指针”这可能对您有所帮助。我不知道,但我是c的新人。我相信你需要它。

答案 3 :(得分:0)

它是否能产生真正的性能差异,您只能通过实现两个版本,启用编译器优化和比较速度来找到它们。这取决于与其他代码相关的太多因素是可预测的。这显然取决于你的函数被实际调用的次数。

但总的来说,内联可能会对速度产生重大积极影响。

保持灵活性,并且假设您显然使用的是C ++(而不是C),那么使用更多 C ++ - 类似的方法是个好主意处理这种情况。有关各种可能性及其含义,请参阅this SO post。如果您遵循问题中列出的策略之一,编译器可能会尽可能地内联,同时您仍然可以获得函数指针的灵活性。