【问题标题】:Creating and using func pointer to method of friend class创建和使用指向朋友类方法的func指针
【发布时间】:2015-07-23 14:31:39
【问题描述】:

我有 2 节课:

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 类”
  • 删除 A::Func()
  • 在 B::FunctionFromB() 中创建函数 ptr
  • 在 B::FunctionFromB() 中进行切换,将上述函数 ptr 初始化为 A::Func1 或 A::Func2。 Switch 类似于 A::Func() 中的那个
  • 不是运行 objectA->Func(x, a, b, c),而是运行 objectA->functionPtr(a, b, c)

如何做到这一点?我尝试使用 std::function 执行此操作,但我不知道如何正确声明/初始化/调用它以使其工作。

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

EDIT2:
提供了帮助,我回答说如何使用 C 风格的函数 ptr 执行此操作,但我想让它与 std::function 一起使用。我是这样做的(注意 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));
}

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

【问题讨论】:

  • 您想了解指向成员函数的指针,例如here.

标签: c++ function class pointers friend


【解决方案1】:

您可以为 EnumType 使用无范围的枚举吗?

enum Enumtype
{
    enumtyp1,
    enumtyp2,
    enumtypmax
};

如果它是一个选项,编译器会免费为您提供到 int 的转换:enumtyp1 -&gt; 0enumtyp2 -&gt; 1enumtypmax -&gt; 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 为零,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;
    }
}

【讨论】:

  • 谢谢,我一定会试试这个;)不幸的是,我今天有很多工作,可能会在 1-2 周内检查。然后我会评论/回答/标记答案。
  • 一件事……我们可以用 std::function 代替 C 类函数类型吗?
  • 恕我直言,std::function 可以工作,但会过分。 对于当前问题,指向方法或方法数组的指针就足够了。
  • 这行得通 - 刚刚试过。我仍然不喜欢使用这个:typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type); 当我们在 Cpp 中有 std::function 时。即使它是一个矫枉过正,你会好心告诉我如何做到这一点?指向成员函数的指针对我来说一直是个问题:/
  • @ForEveR:OP 希望再次看到您的答案 - 对于 MKK:ForEveR 已经使用 std::function 发布了答案并将其删除
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 2020-09-02
  • 2010-09-08
  • 2017-04-13
相关资源
最近更新 更多