c++中的函数指针和类成员函数指针

       在c中函数指针的形式很简单 函数返回type+(*函数名)+参数,为了使用方便我们经常通过typedef来重新定义,下面来看一个例子。

#include 
    
    
     
     

typedef int (*DGUCO_FUNC) (int,int);

//加
int add(int a,int b)
{
    return a + b;
}

//减
int reduce(int a,int b)
{
    return a - b;
}

//乘
int ride(int a,int b)
{
    return a * b;
}

//除
int except(int a,int b)
{
    if (b == 0)
        return 0;
    return a / b;
}


int main(int argc, const char * argv[])
{
    DGUCO_FUNC addFunc = add;
    DGUCO_FUNC reduceFunc = reduce;
    DGUCO_FUNC rideFunc = &ride;
    DGUCO_FUNC exceptFunc = &except;
    
    int a = 6;
    int b = 4;
    
    printf("a + b = %d\n",addFunc(a,b));
    printf("a - b = %d\n",reduceFunc(a,b));
    printf("a * b = %d\n",rideFunc(a,b));
    printf("a / b = %d\n",exceptFunc(a,b));
}
    
    
       这里我们需要注意到一点,前两个函数我没有用取址符,后两个函数我用了取址符有什么不同呢,这里我们可以类比一下数组,int a[10],当我们取a和&a的值时其实是一样的,都是数组的首地址,对于函数来说这两种写法值也是一样的,但是其意义会有所不同,test表示的是函数的首地址,类型是void()类型,而&test是一个指向函数的指针类型是 int (*)(int,int)

在c++普通的函数指针是一样的,如果是类的成员函数指针呢?

//
//  main.cpp
//  Demo
//
//  Created by 杜国超 on 16/12/28.
//  Copyright © 2016年 杜国超. All rights reserved.
//

#include 
    
    
     
     
using namespace std;

class MYClass
{
public:
    static void staticfunc();
    void test(int a,int b);
    virtual void sing();
    virtual void run();
};

void MYClass::staticfunc()
{
    std::cout <<"MYClass staticfunc" << std::endl;
}

void MYClass::test(int a,int b)
{
    std::cout <<"MYClass test=" <<  a + b << std::endl;
}

void MYClass::sing()
{
    std::cout << "MYClass Sing" << std::endl;
}

void MYClass::run()
{
    std::cout << "MYClass run" << std::endl;
}

class ChildClass : public MYClass
{
public:
    void test (int a,int b);
    virtual void sing();
};

void ChildClass::test(int a,int b)
{
    std::cout <<"ChildClass test=" <<  a - b << std::endl;
}

void ChildClass::sing()
{
    std::cout << "ChildClass Sing" << std::endl;
}

typedef	void    (MYClass::* DGUCO_FUNC)(int,int);
typedef	void    (MYClass::* DGUCO_FUNC1)();

typedef	void	(ChildClass::* DGUCO_FUNC2)(int,int);
typedef	void    (ChildClass::* DGUCO_FUNC3)();

typedef	void    (* DGUCO_FUNC4)();

int main(int argc, const char * argv[])
{
    //父类成员函数指针指向父类成员函数
    DGUCO_FUNC func1 = &MYClass::test;
    DGUCO_FUNC1 func2 = &MYClass::sing;

    //父类成员函数指针指向子类覆盖父类成员函数(不允许)
//    DGUCO_FUNC func3 = &ChildClass::test;
//    DGUCO_FUNC1 func4 = &ChildClass::sing;
   
    //子类成员函数指针指向父类和子类成员函数
    DGUCO_FUNC2 func5 = &MYClass::test;
    DGUCO_FUNC2 func6 = &ChildClass::test;

    //子类成员函数指针指向父类和子类成员函数
    DGUCO_FUNC3 func7 = &MYClass::sing;
    DGUCO_FUNC3 func8 = &ChildClass::sing;

    //父类成员函数指针指向父类和子类成员函数
    DGUCO_FUNC1 func9 = &MYClass::run;
    DGUCO_FUNC1 func10 = &ChildClass::run;

    //静态成员函数
    DGUCO_FUNC4 func11 = &MYClass::staticfunc;

    MYClass Ca;
    ChildClass Cb;
    int a = 6;
    int b = 4;
    
    std::cout << "**************************" << std::endl;
    (Ca.*func1)(a,b);
    (Cb.*func1)(a,b);

    std::cout << "**************************" << std::endl;
    //多态调用
    (Ca.*func2)();
    (Cb.*func2)();
    
    std::cout << "**************************" << std::endl;
    (Cb.*func5)(a,b);
    (Cb.*func6)(a,b);

    std::cout << "**************************" << std::endl;
    (Cb.*func7)();
    (Cb.*func8)();

    std::cout << "**************************" << std::endl;
    (Ca.*func9)();
    (Ca.*func10)();
    
    std::cout << "**************************" << std::endl;
    func11();
}

    
    
当遇到c++的类成员函数时会有很大的不同,首先声明函数指针式必须加上类名,其次在使用时会有很大的区别,最明显的就是在赋值时我们必须加上取址符。
执行结果第一眼看上去其实是一脸懵逼,我们来分析一下。
首先看第一组打印,我们用父类的test函数初始化func1,然后分别通过父类和子类调用该函数,结果都调用了父类的函数,在看到结果前认为第二个会调用子类的test'函数,结果我错了,这里应该是通过子类调用父类的函数(类比MYClass::test,java中的super),但是第二组就不同了,因为sing是一个虚函数当你通过父类和子类对象调用时分别调用了自己的函数,由此可见函数指针也是支持多态的。
接着我们看注释掉的两句,这里是不允许的,如果你想把一个父类成员函数指针指向子类的函数,这个函数不能是在子类中重写父类的函数,因为通过父类不能访问到子类的成员,但是反过来就可以。
看第三组,我们分别用父类和子类的成员函数初始化了子类的成员函数指针,这里是允许的,因为我们可以通过子类访问父类的成员,此时相对应的调用了父类和子类的成员函数。到第四组我们看到和第三组又不同了,这里之所以都调用了子类的函数是因为多态导致的,因为我们通过子类对象调用了该函数,并且该函数是虚函数。
第五组是一个通过父类成员函数指针指向子类成员函数,此时因为我们在子类中没有重写父类的该函数所以是允许的,但是如果我们在子类中重写了该函数那么这里是不允许的。
第六组是一个类成员静态函数的用法,此时静态类成员类成员函数的函数指针声明方式跟普通函数是一样的,但是使用时是和类成员函数的用法。
最后还有一点我们要注意,一个父类成员函数指针,在调用函数式我们可以过父类和子类对象来调用,但是一个子类成员函数指针我们只能通过子类对象来调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值