#include <iostream>
#include 
<string>

using namespace std;

void alert( string msg )
{
    cout 
<< msg << endl;
}

void (*GetFunction())(string)
{
    
return alert;
}

int main()
{
    
//    刚看完C++ Primer第七章,合上书,写个复杂点的函数试一下,刚开始函数声明不是这样的,一点点往上加后来才变成了void (*((*ptr)()))(string)。
    
//写完后就有种预感——明天看了估计就看不懂了,赶紧记下来,呵呵。
    
//    正在从C#转C++,这是在园子C++版里的第一篇文章,有错的地方请大家不要给面子,该拍砖拍砖;-)

    
//ptr是一个指针,他指向一个函数,这个函数返回一个指针,该指针指向一个函数,这个函数带有一个string参数,但是没有返回值
    void (*((*ptr)()))(string= GetFunction;

    
//写完了声明然后调用,刚开始我写的是(*ptr)()("Hello C++"),一运行结果出来了,挺开心,可是在重读一遍的时候发现自己写“错”了,忘了解引用可是结果怎么是对的?
    
//接着又写了(*((*ptr)()))("Hi C++"),F5,结果也出来了于是刚从函数声明中解脱出来的大脑又晕了

    (
*ptr)()("Hello C++");
    (
*((*ptr)()))("Hi C++");

    
//为什么呢,难道函数指针在调用时解不解引用都可以吗?为了证明这个结论,再声明一个的函数指针试一下
    void  (*ptrAlert)(string);
    ptrAlert 
= alert;

    
//不解引用
    ptrAlert("Hello Alert"); 

    
//解引用
    (*ptrAlert)("Hi Alert");

    
/*
        结论:函数指针在调用时解不解引用都可以

        在网上搜到的相关资料:

            围绕这两种写法,当初C89制定的时候曾经有过争论。(*p)();是一种旧式的规定,旧式规定圆括号左边必须具有“函数”类型,如果是指向函数的指针,
        那么必须加上*声明符。但C89不再把圆括号的左边限定为“函数”类型,而是一个后缀表达式。那么问题就来了,如果p的值是函数地址,那么*号就是声明符,
        但如果p指向的内容是函数地址,*号就得被看作运算符了。同一种形式会有两种解释,这是一个矛盾。不仅函数调用如此,指向数组的指针也存在这种矛盾。
        编译器为了处理这种情况得增加代码,效率自然就降低了。争论的最后结果是谁也不能把对方完全说服,于是就干脆两种都支持了。
        
        说实话,我没怎么看懂上面的话,因为不了解C89这些标准,只是觉得(*p)()容易理解些,虽然写着麻烦点,以后c++程序写多了应该会有更深的认识吧。
    
*/
}