C ++ - 关于函数指针的问题

时间:2010-11-17 16:28:10

标签: c++ pointers

我写了以下代码:

#include "stdafx.h"
#include <iostream>
using namespace std;

double funcA()
{
    return 100.0;
}

int g(double (*pf)())
{
    cout << (*pf)() << endl;
    return 0;
}

int g2(double pf())
{
    cout << pf() << endl;
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    g(&funcA);  // case I
    g(funcA);   // case II

    g2(funcA);  // case III
    g2(&funcA); // case IV
    return 0;
}

我在VS2008上运行了上面的代码,每个函数调用返回'100'。 这是一个问题:

Q1&GT;代码中有问题吗?

Q2&GT;似乎C ++在* pf和pf之间没有区别。这是对的吗?

谢谢

5 个答案:

答案 0 :(得分:8)

实际上,

C ++ 确实区分了double()double(*)()类型,但区别是微妙的。将函数类型作为参数传递给函数时,函数类型会自动“降级”为函数指针。 (我想,这与数组类型在作为函数参数传递时如何降级为指针类型类似。)

但是,根据C ++类型系统,函数类型和函数指针类型仍然是不同的类型。考虑以下情况:

void g() { }

template <class F>
struct Foo
{
    Foo(const F& f) : func(f)
    { }

    void operator()() { func(); }

    F func;
};


int main ()
{
    Foo<void()> f(g);
    f();
}

这应该无法编译,因为您不能将函数类型声明为自动变量。 (请记住,函数不是C ++中的第一类对象。)因此声明F func;无效。但是,如果我们将main函数更改为使用函数指针来实例化模板,如下所示:

int main ()
{
    typedef void(*function_pointer)();
    Foo<function_pointer> f(g);
    f();
}

...现在它编译。<​​/ p>

答案 1 :(得分:2)

以下功能相同:

int g(double (*pf)())
{
    cout << (*pf)() << endl;
    return 0;
}

int g2(double pf())
{
    cout << pf() << endl;
    return 0;
}

取消引用函数指针(如g所示)与调用该函数的名称相同。

  

Q2&GT;似乎C ++没有   * pf和pf之间的差异。就是它   正确的吗?

* pf和pf(作为变量)之间存在差异。如果pf是一个函数,* pf和pf()是相同的(注意括号)。

答案 2 :(得分:0)

对于大多数现代编译器,“(* variable)”之间没有区别。和“变量 - &gt;”。但是,必须检查正在使用的类以查看它是否覆盖取消引用运算符。

许多程序员在定义函数指针时使用typedef,主要是为了使阅读更容易。此外,double pf()语法可能容易出现可读性错误,并且可能与在参数行上执行函数混淆。

答案 3 :(得分:0)

您发布的代码没有问题或不同之处。但是,如果您正在编写带有仿函数的模板,则应使用g2中的语法。请考虑以下事项:

template<typename Iter, typename Func>
void for_each(Iter begin, Iter end, Func functor)
{
    for(; begin != end; ++begin)
    {
        functor(*begin);
    }
}

请注意,如果将解除引用运算符放在functor之前,则会限制已写入函数指针的算法的效用。但是,如果你不把它放在那里,有人可以传递一个STL仿函数,例如std::bind2nd返回的东西。

因此,我总体建议尽可能使用第二种语法(没有*)。

答案 4 :(得分:0)

考虑以下代码

void pf();

void (&prf)() = pf; // OK, bind prf to pf
void (&prf)() = &pf; // ill-formed, can't bind prf to an function pointer value

另一方面

void (*ppf)() = pf; // OK, function decays to a pointer
void (*ppf)() = &pf; // OK, pointer assigned to a pointer

因此存在从函数到指针的隐式转换(称为“衰减”)。这也使你能够说***...***pf - 任意多次取消引用它 - 在每一步中都会发生指针转换的函数,这会撤消前一个解除引用的影响。

在函数参数列表中,T f()T (*f)()是声明参数的等效方式(拼写除外)

void f(void g()); // g has type void (*)()
void f(void (*g)()); // g has type void (*)()

参考将禁止此参数类型调整

void f(void (&g)()); // g has *not* the type void (*)()

这与数组声明的参数完全相同:参数永远不是数组,但如果它们被声明为数组,它们将始终是指针。