创建并使用指向友类方法的函数指针

Creating and using func pointer to method of friend class

本文关键字:类方法 函数 指针 创建      更新时间:2023-10-16

我有两个类:

enum class Enumtype
{
    typ1,
    typ2,
};
class A
{
private:
    retType Func1(arg1Type, arg2Type, arg3Type);
    retType Func2(arg1Type, arg2Type, arg3Type);
public:
    A();
    retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
}
class B
{
private:
    arg1Type a;
    arg2Type b;
    arg3Type c;
public:
    int FunctionFromB(Enumtype);
}

最初的用法是:

int B::FunctionFromB(Enumtype x)
{
    A* objectA;
    for(int i=0; i<whatever; i++)
    {
        objectA->Func(x, a+i, b+(2*i), c+(3*i));
    }
}
retType A::Func(Enumtype x, arg1type a, arg2type b, arg3type c)
{
    switch(x)
    {
    case Enumtype::typ1:
        return Func1(a, b, c);
    case Enumtype::typ2:
        return Func2(a, b, c);
    default:
        return Func1(a, b, c);
    }
}

不幸的是,我不想运行switch每一个循环,所以我想到了这个:

  • 在A类中写入"友类B"
  • 删除:Func ()
  • 创建函数ptr在B::FunctionFromB()
  • 在B::FunctionFromB()中做开关,它将上述函数ptr初始化为A::Func1或A::Func2。开关将类似于A::Func()
  • 中的开关
  • 代替运行objectA->Func(x, a, b, c),运行objectA->functionPtr(a, b, c)

如何做到这一点?我试着用std::function来做这件事,但我不知道如何正确地声明/初始化/调用它来使它工作。

编辑:


我编辑了FunctionFromB,因为我跳过了一个重要的部分-> Func在循环中使用不同的参数被调用。

EDIT2:
给出了帮助,我有答案说如何用c风格的函数ptr做到这一点,但我想让它用std::函数工作。我是这样做的(注意类B和enum是相同的):

class A
{
private:
    retType Func1(arg1Type, arg2Type, arg3Type);
    retType Func2(arg1Type, arg2Type, arg3Type);
public:
    A();
    typedef std::function<retType(arg1Type, arg2Type, arg3Type)> funcPtr;
}
int B::FunctionFromB(Enumtype typeB)
{
    A* objectA;
    A::funcPtr func = nullptr;
    switch(type)
    {
    case Enumtype::typ2:
        func = std::bind(&A::Func2, objectA, std::placeholders::_1,
                            std::placeholders::_2, std::placeholders::_3);
        break;
    case Enumtype::typ2:
    default:
        func = std::bind(&A::Func1, objectA, std::placeholders::_1,
                            std::placeholders::_2, std::placeholders::_3);
        break;
    }
    for(int i=0; i<whatever; i++)
        func(a+i, b+(2*i), c+(3*i));
}

,我想,它是有效的。如果有人在这里发现错误或更好的方法,请告诉我;)

您可以为EnumType使用无作用域的enum吗?

enum Enumtype
{
    enumtyp1,
    enumtyp2,
    enumtypmax
};

如果它是一个选项,编译器将免费为您提供到int的转换:enumtyp1 -> 0, enumtyp2 -> 1, enumtypmax -> 2(根据3.9.2§10 枚举数的值或无作用域枚举类型的对象的值被转换为整数积分促销

)

根据3.9.2§2 保证值枚举器列表被声明为常量,并且可以出现在需要常量的任何地方。一个enumeratordefinitionWith =为关联的枚举数提供常量表达式所指示的值。如果是第一个枚举数没有初始化项,相应常量的值为零。一个enumerator-definition如果没有初始化式,则向枚举数提供通过增加前一个枚举数的值而获得的值。

enum { a, b, c=0 };
enum { d, e, f=e+2 };

定义a、c、d为0,b、e为1,f为3。

您可以在a中构建a方法的静态数组,并使用直接数组索引,这应该比开关更简单:

enum Enumtype
{
    enumtyp1,
    enumtyp2,
    enummax
};
class A
{
private:
    typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
    retType Func1(arg1Type, arg2Type, arg3Type);
    retType Func2(arg1Type, arg2Type, arg3Type);
    static funcx fp[enummax];
public:
    A();
    retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
};
class B
{
private:
    arg1Type a;
    arg2Type b;
    arg3Type c;
public:
    int FunctionFromB(Enumtype);
};
int B::FunctionFromB(Enumtype x)
{
    A* objectA;
    for(int i=0; i<whatever; i++)
    {
        objectA->Func(x, a+i, b+(2*i), c+(3*i));
    }
    return whatever;
}
retType A::Func(Enumtype x, arg1Type a, arg2Type b, arg3Type c)
{
    funcx f = A::fp[x];
    return (this->*fp[x])(a, b, c);
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };

或者,您可以在B::FunctionFromB中直接获得一个指针,并直接重复调用它:

enum Enumtype
{
    enumtyp1,
    enumtyp2,
    enummax
};
class A
{
public:
    typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
private:
    retType Func1(arg1Type, arg2Type, arg3Type);
    retType Func2(arg1Type, arg2Type, arg3Type);
    static funcx fp[enummax];
public:
    A();
    friend class B;
};
class B
{
private:
    arg1Type a;
    arg2Type b;
    arg3Type c;
    A::funcx getFunc(Enumtype);
public:
    int FunctionFromB(Enumtype);
};
A::funcx B::getFunc(Enumtype x){
    return A::fp[x];
}
int B::FunctionFromB(Enumtype x)
{
    A* objectA;
    A::funcx funcPtr = getFunc(x);
    for(int i=0; i<whatever; i++)
    {
        (objectA->*funcPtr)(a+i, b+(2*i), c+(3*i));
    }
    return whatever;
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };

在后一种情况下,您可以避免在A中声明方法数组,坚持为EnumType使用有作用域的enum,并在每次调用B::FunctionFromB时使用一次转换:

A::funcx B::getFunc(Enumtype x){
    switch (x) {
        case EnumType::typ1:
            return &A::Func1;
        case EnumType::typ2:
            return &A::Func2;
        case default:
            return &A::Func1;
    }
}