我有一个独特的问题,我试图解决,我无法找到一个好的解决方案。我知道这可能不是最好的架构,但我正在探索解决方案。
我们说我有一个基类,还有两个继承自这个基类的子类。子类具有混合的唯一函数,这些函数都具有相同的函数原型(相同的返回值和参数)。
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;
}
这可能吗?如果没有,这是否可以使用模板?
答案 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
希望这有帮助!