创建和使用 friend class 方法的 func 指针

Creating and using func pointer to method of friend class

我有 2 个 classes:

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);
    }
}

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

如何做到这一点?我试着用 std::function 来做到这一点,但我不知道如何正确地 declare/initialize/call 让它工作。

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

编辑2:
提供了帮助,我得到的答案是如何使用 C 风格的函数 ptr 执行此操作,但我想让它与 std::function 一起使用。我是那样做的(注意 class B 和枚举是一样的):

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 Enumtype
{
    enumtyp1,
    enumtyp2,
    enumtypmax
};

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

根据 3.9.2 §2 保证这些值 enumerator-list 被声明为常量,并且可以出现在任何需要常量的地方。枚举器定义 with = 为关联的枚举器提供常量表达式指示的值。如果第一个 枚举数没有初始化器,对应常量的值为零。枚举器定义 没有初始值设定项时,为枚举器提供通过增加前一个枚举器的值而获得的值 一个。

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 的作用域枚举,并在每次调用 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;
    }
}