是否可以使用子类的成员函数指针?

时间:2018-03-22 18:44:09

标签: c++ member-function-pointers

我有一个独特的问题,我试图解决,我无法找到一个好的解决方案。我知道这可能不是最好的架构,但我正在探索解决方案。

我们说我有一个基类,还有两个继承自这个基类的子类。子类具有混合的唯一函数,这些函数都具有相同的函数原型(相同的返回值和参数)。

Class Base
{
  Base(){}     
}

Class Child : Base
{
  Child(){}  
  void FunctionA(int Arg1, int Arg2){};
  void FunctionB(int Arg1, int Arg2){};
}

Class WildChild : Base
{
  WildChild(){}  
  void FunctionC(int Arg1, int Arg2){};
  void FunctionD(int Arg1, int Arg2){};
}

有没有办法定义成员函数指针,以便Base类可以使用这些函数指针,即使Base类没有实现相应的函数?

我理解的方式是子类需要实现自己的函数指针定义,并且可以填充函数指针表...

对于孩子

typedef void (Child::*ChildFunctionPtrType)(int Arg1, int Arg2);
ChildFunctionPtrType funcPtrTable[2];
funcPtrTable[0] = &Child::FunctionA;
funcPtrTable[1] = &Child::FunctionB;

对于WildChild

typedef void (WildChild::*WildChildFunctionPtrType)(int Arg1, int Arg2);
WildChildFunctionPtrType funcPtrTable[2];
funcPtrTable[0] = &WildChildFunctionPtrType::FunctionC;
funcPtrTable[1] = &WildChildFunctionPtrType::FunctionD;

但我真正需要的是一个函数指针表,可以由Base类使用,但包含指向Child类中成员函数的指针。

typedef void (Base::*FunctionPtrType)(int Arg1, int Arg2);
Class Base
{
  Base(){}              
  FunctionPtrType funcPtrTable[SIZE_OF_TABLE];
}

Child::PopulateTable
{
  funcPtrTable[0] = &Child::FunctionA;
  funcPtrTable[1] = &Child::FunctionB;
}

WildChild::PopulateTable
{
  funcPtrTable[0] = &WildChild::FunctionC;
  funcPtrTable[1] = &WildChild::FunctionD;
}

这可能吗?如果没有,这是否可以使用模板?

1 个答案:

答案 0 :(得分:0)

此范例对于创建可测试系统和模拟对象非常有用,但请记住,它可能比虚拟函数昂贵得多。

答案是使用std :: function和std :: bind(C ++ 11及更高版本)。这是一个例子:

#include <functional>
#include <iostream>
#include <string>

class Base
{
public:
    Base() { }

    void functionA(int a, int b) {
        if (fnA_) {
            fnA_(a, b);
        }
    } 
    void functionB(int a, int b) {
        if (fnB_) {
            fnB_(a, b);
        }
    } 
protected:
    typedef std::function<void(int, int)> FunctionA;
    typedef std::function<void(int, int)> FunctionB;

    FunctionA& fnA() { return fnA_;}
    FunctionB& fnB() { return fnB_;}

private:
    FunctionA fnA_;
    FunctionB fnB_;
};

class Child : public Base {
public:
    Child() {
        fnA() = std::bind(&Child::functionAImpl, this, std::placeholders::_1, std::placeholders::_2);
        fnB() = std::bind(&Child::functionBImpl, this, std::placeholders::_1, std::placeholders::_2);
    }
private:
    // Please make them different names
    void functionAImpl(int a, int b) {
        std::cout << "Child::functionAImpl: a=" << a << ", b=" << b << std::endl;
    } 
    void functionBImpl(int a, int b) {
        std::cout << "Child::functionBImpl: a=" << a << ", b=" << b << std::endl;
    } 
};

class WildChild : public Base {
public:
    WildChild() {
        fnA() = std::bind(&WildChild::functionAImpl, this, std::placeholders::_1, std::placeholders::_2);
        fnB() = std::bind(&WildChild::functionBImpl, this, std::placeholders::_1, std::placeholders::_2);
    }
private:
    // Please make them different names
    void functionAImpl(int a, int b) {
        std::cout << "WildChild::functionAImpl: a=" << a * 2 << ", b=" << b * -3 << std::endl;
    } 
    void functionBImpl(int a, int b) {
        std::cout << "WildChild::functionBImpl: a=" << a * -4 << ", b=" << b * 5 << std::endl;
    } 
};
int main(int argc, const char** argv) {
    Child child;
    child.functionA(3, 4);
    child.functionB(5, 6);
    WildChild wildChild;
    wildChild.functionA(3, 4);
    wildChild.functionB(5, 6);
    return 0;
}

这是clang的输出:

clang++ --std=c++11 -g today.cpp && ./a.out
Child::functionAImpl: a=3, b=4
Child::functionBImpl: a=5, b=6
WildChild::functionAImpl: a=6, b=-12
WildChild::functionBImpl: a=-20, b=30

希望这有帮助!