在得到this question的答案后,我发现有两种有效的方法来定义函数指针。
typedef void (Function) ();
typedef void (*PFunction) ();
void foo () {}
Function * p = foo;
PFunction q = foo;
我现在更喜欢Function * p
而不是PFunction q
,但显然这不适用于指向成员的指针函数。考虑一下这个人为的例子。
#include <iostream>
struct Base {
typedef void (Base :: *Callback) ();
//^^^ remove this '*' and put it below (i.e. *cb)
Callback cb;
void go () {
(this->*cb) ();
}
virtual void x () = 0;
Base () {
cb = &Base::x;
}
};
struct D1 : public Base {
void x () {
std :: cout << "D1\n";
}
};
struct D2 : public Base {
void x () {
std :: cout << "D2\n";
}
};
int main () {
D1 d1;
D2 d2;
d1 .go ();
d2 .go ();
}
但是,如果我将其更改为新的首选样式:typedef void (Base :: Callback) ()
和Callback * cb
,则会在typedef
处得到一个编译器错误
回调成员‘
’的额外限定'Base::‘
为什么不允许这样做?这只是一个疏忽,还是会导致问题?
发布于 2011-09-15 19:00:31
对于非成员函数,像typedef void(Function)()
这样的类型有多种用途,但对于成员函数,唯一的应用是声明一个保存函数指针的变量。因此,除了风格偏好之外,没有严格的需要允许这种语法,标准中也省略了它。
背景
::
是一个作用域解析操作符,如果static
是类类型,则语法X::Y
保留用于X
成员访问。因此,X::*Z
是另一种用来定义成员指针的语法。
暂时忘掉成员函数,只需考虑一下成员数据,然后看看下面的代码:
struct X
{
int a;
};
int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;
它定义了一个指向成员数据的指针,cout
使用它来打印object x
的a
的值,并打印:
100
演示:http://www.ideone.com/De2H1
现在想一想,如果允许X::pa
(而不是X::*pa
)这样做,那么上面的代码是这样写的:
int X::pa = X::a; //not &X::a
看到这种语法,您如何判断X::a
是static
成员还是非静态成员?这就是为什么标准提出了指向成员的指针语法,并将其统一应用于非静态成员数据和非静态成员函数。
事实上,你不能写X::a
,你必须写&X::a
。语法X::a
会导致编译错误(参见this)。
现在将这个成员数据的参数扩展到成员函数。假设你有一个定义为:
typedef void fun();
那么你认为下面的代码是做什么的呢?
struct X
{
fun a;
};
它定义了fun
类型的成员a
(这是一个不带参数的函数,返回空值),等同于:
struct X
{
void a();
};
惊讶吗?继续往下读。
struct X
{
fun a; //equivalent to this: void a();
};
void X::a() //yes, you can do this!
{
cout << "haha" << endl;
}
我们可以使用完全相同的语法来引用a
,它现在是一个成员函数:
X x;
x.a(); //normal function call
void (X::*pa)() = &X::a; //pointer-to-member
(x.*pa)(); //using pointer-to-member
相似之处在于右侧的联轴器:&X::a
。无论a
引用成员函数还是成员数据,语法都是相同的。
演示:http://www.ideone.com/Y80Mf
结论:
因为我们知道,无论a
是成员数据还是成员函数,我们都不能在RHS上编写X::a
。唯一允许的语法是&X::f
,这使得目标类型(在LHS上)也必须是指针,这反过来使得语法void (X::*pa)()
是绝对必要的和基本的,因为它适合语言中的其他语法。
发布于 2011-09-15 19:08:10
准确地说,在非成员指针的情况下,两个类型定义函数是不同的:
typedef void function();
typedef void (*fptr)();
第一个将function
定义为不带参数并返回void
的函数,而第二个将ftpr
定义为指向不带参数且返回void
的函数的指针。可能会出现混淆,因为在许多上下文中,函数类型将被隐式转换为指针类型。但不是全部:
function f; // declares void f();
struct test {
function f; // declares void test::f()
};
void g( function f ); // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f ); // calls g( &f ): function decays to pointer to function
void f() {} // definition of f
// function h = f; // error: cannot assign functions
function *h = f; // f decays to &f
发布于 2011-09-15 20:12:29
让我们暂时跳过“函数”部分。在C++中,我们有int
、int*
和int Foo::*
类型。这是一个常规整数,指向整数的指针,以及指向整数成员的指针。没有第四种类型“整数成员”。
同样的道理也适用于函数:没有类型“成员函数”,即使有函数类型、函数指针类型和成员函数指针类型。
https://stackoverflow.com/questions/7429510
复制相似问题