2012-01-03 170 views
-1

我有一个代码。这段代码为什么要编译?

class A 
{ 
public: 
    int foo(int i) 
    { 
     return i; 
    } 
}; 

int foo(int i) 
{ 
    return i; 
} 

int (A::*ptrFoo)(int) = NULL; 
int (*_foo)(int) = NULL; 

int main() 
{ 
    ptrFoo = &A::foo; 
    _foo = foo; 

    (*_foo)++++++++++++++(10); //This dont compile... 

    A a; 
    (a.*ptrFoo)+++++++++++++++++(10); //This compiles ???? 

} 

请告诉我它是什么?一个未定义的行为或什么?我编译它在VS2008.Strangely最后一行代码编译成功。

+2

'++++++++++++++'是七个半后增量运算符。据推测,编译器已经陷入了一半。 – 2012-01-03 05:47:14

+0

您是否将它编译为C和C++?或者你为什么包含这两个标签? – 2012-01-03 05:53:21

+0

我编译它在c + +(VS2008).i将删除“C”标记 – YAHOOOOO 2012-01-03 06:01:09

回答

2

这两个表达式都不应该编译:在C++中,不能对指向函数或成员函数的指针或函数类型或成员函数执行算术运算。程序中的两个表达式分别尝试对函数和成员函数执行算术运算。

如果您的编译器接受第二个表达式,这是由于编译器中的错误。

1

首先请注意,指向函数的指针与指向成员函数的指针不同。

你的第一个例子是一个指向普通函数的指针。它包含该函数的实际内存地址。当你取消引用((*_foo))时,你会得到这个函数本身,算术运算包括++在函数上(函数指针)是毫无意义的。

第二个是另一个故事,指向类成员函数的指针不会在内存中携带该函数的地址。实际上编译器如何管理成员函数是特定于实现的。指向成员函数的指针可能包含一些地址或者某些编译器特定的信息。这种类型的算术也没有意义。

因此,我们不知道(a.*ptrFoo)的价值是什么,但在您的情况下MSVC2008设法编译它,无论是因为错误还是设计。

顺便说一下,GCC不会编译这两个语句中的任何一个,并在两者上抛出错误。

无论你是偶数还是奇数,无论如何,我们正在做算术。 (如果有奇数+那么就没有函数调用,就像在第二个例子中一样,你将函数递增8次,然后最后一个剩余的+增加10个结果。正试图改变一个函数/成员函数指针。)

+0

“编译器如何管理成员函数是特定于实现的”非成员函数的实现也是一个实现细节。 – 2012-01-03 06:26:47

+0

@JamesMcNellis:你说的对,但是每一个普通的函数在内存中都有一个明确的地址,不是吗?但是,成员函数的“地址”并不是我们所知道的;每个编译器都有自己的实现类的范例。 – Hossein 2012-01-03 06:30:54