是否可以通过指针调用过程?我没有在互联网上找到任何关于它的信息,但是下面的实验代码在没有警告的情况下编译。
#include <iostream>
#include <ctime>
using namespace std;
void PrintCurrentClock()
{
cout<<clock()<<endl;
}
void PrintCurrentTimeStamp()
{
cout<<time(0)<<endl;
}
int main()
{
void* pF = PrintCurrentClock;
pF;
pF = PrintCurrentTimeStamp;
pF;
system("Pause");
return 0;
}
输出为空,好像*pF
有点“透明”。
答案 0 :(得分:5)
C和C ++都有函数指针,可以让你做你想要的事情:
void (*pf)(void);
pf = FunctionWithVeryVeryVeryLongNameThatPrintsTheCurrentClockStateUsingStdCoutOutputStream;
pf();
括号中的void
是可选的。
您没有找到关于该主题的任何内容的原因是,由于历史原因,C中的函数和过程都被称为函数(原因是原始语言中没有void
- 返回的过程{{1默认情况下,返回值被忽略)。 C ++继承了这种命名约定。
答案 1 :(得分:4)
你想要的是函数指针:
void (*pF)() = PrintCurrentClock;
pF();
(有些人认为写&PrintCurrentClock
是更好的风格)
请注意,正如您所看到的,函数指针有一个非常笨拙的语法(特别是如果您开始使用带有“奇怪”参数的函数指针)并且可以阻止某些编译器优化正常工作,因此它们通常仅在实际上需要(例如,对于回调,虽然在C ++中通常首选仿函数)。
为什么你的代码会编译,虽然它不能按预期工作?在
void* pF = PrintCurrentClock;
PrintCurrentClock
是void (*pF)()
,隐式转换为void *
1 ;然后,写作
pF;
您正在评估表达式pF
并丢弃其返回值 - 这实际上是一个无操作(就像您编写5;
或任何其他不涉及函数调用的表达式一样)。
实际上,这种转换不应该自动发生,因为C ++标准不提供从函数指针到void *
的隐式转换。用g ++ 4.6正确编译它会产生错误:
matteo@teolapmint ~/cpp $ g++ -Wall -Wextra -ansi -pedantic testfuncptr.cpp
testfuncptr.cpp: In function ‘int main()’:
testfuncptr.cpp:19:20: error: invalid conversion from ‘void (*)()’ to ‘void*’ [-fpermissive]
testfuncptr.cpp:21:15: warning: statement has no effect [-Wunused-value]
testfuncptr.cpp:23:22: error: invalid conversion from ‘void (*)()’ to ‘void*’ [-fpermissive]
testfuncptr.cpp:25:23: warning: statement has no effect [-Wunused-value]
testfuncptr.cpp:27:39: error: ‘system’ was not declared in this scope
告诉您这些转化不被允许,pF;
说明是无操作且您忘记了#include <cstdlib>
(尽管system("pause");
无法移植)。
答案 2 :(得分:2)
您创建和使用函数指针的方式稍微偏离。以下是如何执行此操作的示例:
void proc() {
cout << "Hello from proc" << endl;
}
...
void (*pproc)() = proc;
pproc();
答案 3 :(得分:1)
是的,你可以:
虽然类型系统有点复杂 因此通常将指针包装到typedef中的函数。
typedef <returnType> (*<TypeName>)(<ParameterList>);
// In your case:
tpyedef void (*PtrToTimeFunc)();
// Now your pointer types look like normal variables:
PtrToTimeFunc pf = &PrintCurrentTimeStamp;
// Calling them is like normal:
pf(); // If it needed parameters then put them as normal.
因为C ++编译器不能通过函数指针来优化代码;在C ++中,通常使用仿函数。仿函数是一个行为类似函数的对象,但因为它是一个对象,也可以包含状态(就像其他语言中的闭包一样)。
struct MyFunctor
{
// To make a functor just override the operator ()
// You can make it return any type and take any parameters (just like a function).
int operator()() const
{
return time(NULL);
}
// Add any state and constructors etc. you like here.
// Though note: because I declared the operator() as const you
// can not mutate the state via the function call (remove cost)
// if you want to do that.
};
// declaring a functor just like any-other object.
MyFunctor myFunctor;
// calling. Just like a function.
myFunctor();
行。那么为什么这比指针更有用呢。
与标准算法一起使用时。您可以使用functor
的类型定义算法,因此编译器会生成算法代码,它也可以使用仿函数的所有代码(与它无法优化的函数指针不同)。这允许编译器完成一整套优化。
std::generate(cont.begin(), cont.end(), myFunctor);
所以在C ++ 11中我们引入了lambdas。这些基本上是可以定义的功能。但是将lambda视为编译器生成的仿函数更容易(因为它们can
捕获当前状态作为其定义的一部分)。
std::generate(cont.begin(), cont.end(), [](){return time(NULL);});
// [] - defines the state that is being captured.
// Think of this like the constructor capturing objects.
// In this case take no state.
//
// () - parameter list
// In this case no parameters
//
// {} - The code.
一个更有趣的例子:
std::vector<int> data; // fill vector
std::for_each(data.begin(), data.end(), [](int& value){value += 4;}); // Add 4 to each member.