void函数指针的二维数组c ++

Posted

技术标签:

【中文标题】void函数指针的二维数组c ++【英文标题】:Two-dimensional array of void function pointers c++ 【发布时间】:2014-11-21 06:47:33 【问题描述】:

我正在尝试在 2 台计算机“玩家”之间构建一个高效的 Rock、Paper、Scissors 模拟器。我看到here 的一个建议是使用矩阵来存储可能的结果。我真的很喜欢这个想法,因为这意味着我不必有 9 个不同的 if() 语句来解释所有可能的值。每当一场比赛完成时,我都有函数来迭代每个玩家的赢、输和平局的数量。因此,我认为如果我可以构建一个函数指针的二维数组,这样 [0][0] 代表双方抛出“Rock”并导致 Draw,抛出函数 addDraw( ) 为每个玩家。我找到了一个函数指针的一维数组的示例,它可以工作here。

当我尝试编译时,我的代码抛出了几个错误。如果还需要什么,请告诉我。

调用结果的函数:

void Player::result(vector<Player*> &vals, int x, int y)

    Player *p1 = vals[0];
    Player *p2 = vals[1];

    void(*results1[3][3]) =
    
         p1->addDraws, p1->addWins, p1->addLosses ,
         p1->addLosses, p1->addDraws, p1->addWins ,
         p1->addWins, p1->addLosses, p1->addDraws 
    ;

添加赢、输和平的功能:

void Player::addWins()

    wins++;


void Player::addLosses()

    losses++;


void Player::addDraws()

    draws++;

所有函数都在 Player.h 中初始化并在 Player.cpp 中声明(我认为这是正确的术语)。我收到的最常见错误是“错误 C2440: 'initializing' : cannot convert from 'void (__thiscall Player::* )(void)' to 'void *'

【问题讨论】:

所有函数都在 Player.h 中声明并在 Player.cpp 中定义。这是正确的。 您声明了一个指向void 的3x3 指针数组,您的意思可能是void(Player::* results1[3][3])();(假设函数不是static)。如果你真的想在不失去理智的情况下走这条路,你应该首先typedef 成员函数指针类型。使用指针时,您还需要提供一个对象。 【参考方案1】:

你有一个 void 指针数组,不是函数指针,成员函数也不是函数指针。

你需要类似的东西

typedef void (Player::*Score)();  // typedefs and function types go together well
Score scores[3][3]) =

     &Player::addDraws, &Player::addWins, &Player::addLosses ,
     &Player::addLosses, &Player::addDraws, &Player::addWins ,
     &Player::addWins, &Player::addLosses, &Player::addDraws 
;

// Calling
Player a;
(a.*scores[0][0])();

或者,使用这样的免费函数:

void addWins(Player* p)

    p->addWins();


// Similar for the others...

typedef void (*Score)();
Score scores[3][3] =  addWins, .... 

//
Player* player = ...
scores[0][0].addWins(player);

或者,你可以是现代人并使用std::function

【讨论】:

我希望我在使用 c++ 方面足够成熟,知道如何使用 std:function。 一直在互联网上寻找相关问题的解决方案,这是最简单的一个,从长远来看(并且也有效)。我已经省略了 typedef,因为我发现它是多余的。【参考方案2】:
void (*results1[3][3]) = 
     p1->addDraws, p1->addWins, p1->addLosses ,
     p1->addLosses, p1->addDraws, p1->addWins ,
     p1->addWins, p1->addLosses, p1->addDraws  ;

我觉得应该是这样的

void (*results1[3][3])() = 
     p1->addDraws, p1->addWins, p1->addLosses ,
     p1->addLosses, p1->addDraws, p1->addWins ,
     p1->addWins, p1->addLosses, p1->addDraws  ;

或者,你可以使用 typedef

typedef void (*func)();
func results1[3][3] = 
         p1->addDraws, p1->addWins, p1->addLosses ,
         p1->addLosses, p1->addDraws, p1->addWins ,
         p1->addWins, p1->addLosses, p1->addDraws  ;

【讨论】:

谢谢,傅敏。虽然仍然抛出:错误 C2440: 'initializing' : cannot convert from 'overloaded-function' to 'void (__cdecl *)(void)'【参考方案3】:

在 C++ 中,方法不是函数。如果您的计数器在类实例中,则调用的代码需要知道this 才能执行。

解决问题有几种方法:

    不要使用void (*)() 函数,而是使用void (*)(MyClass *) 并将要更新的实例传递给函数

    使用指向成员的指针。这在引擎盖下基本相同,但语法有点奇怪;类型是void (MyClass::*)(),要使用成员指针进行调用,语法将使用奇怪的-&gt;* 运算符,例如(this-&gt;*m[i][j])()

    使用闭包。这需要 C++11 并且从语法的角度来看更简洁;而不是使用指向函数的指针矩阵,而是使用捕获对象实例的std::function&lt;void()&gt; 对象矩阵。 C++ 闭包无法处理向上的 funarg 问题,但在您的情况下,这应该不是问题(在我看来,不需要让其中一个闭包在持有计数器的实例中幸存下来)。

然而,在非常具体的情况下,我根本不会使用指向函数的指针,而是使用带有结果 (0, 1, 2) 的整数矩阵,然后更新结果代码只是

results[m[i][j]]++;

没有ifs,也没有涉及电话。在这个想法中,results 是一个由三个整数组成的数组,其中包含 A 获胜、B 获胜和平局的计数器。

【讨论】:

以上是关于void函数指针的二维数组c ++的主要内容,如果未能解决你的问题,请参考以下文章

请问 对于指向函数的指针,前面的括号(int (*)(void*,void*))代表啥呢?谢谢

C语言如何给用函数二维数组动态赋值

C-二维数组, 字符串, 指针

C语言二维数组问题

指针的这些知识你知道吗?C语言超硬核指针进阶版3w+字详解+指针笔试题画图+文字详细讲解

C语言中 指针做函数参数传递二维数组