C ++如何识别要使用的函数(与类成员函数指针相关)

用户名

我有一个关于类成员函数的问题。这涉及继承。我在下面编写了以下代码,但是我并不能完全理解它的工作原理(我只能猜测):

#include <iostream>

using namespace std;

class Base
{
};

typedef void(Base::*handler)();

#define selector(_SELECTOR) static_cast<handler>(&_SELECTOR)

class Boo : public Base
{
public:
    void callingFunc()
    {
        cout << "Hey there" << endl;
    }

};


class Foo
{   
public:
    void setCallback( Base * instance,  void (Base::*funcToCall)(void) )
    {
        this->instance = instance;
        this->funcToCall = funcToCall;
    }

    void doCall()
    {
        (instance->*funcToCall)();
    }

private:
    Base* instance;
    void (Base::*funcToCall)(void);
};

void main()
{
    Foo * foo = new Foo();
    Boo * boo = new Boo();

    foo->setCallback(boo, selector(Boo::callingFunc) );
    foo->doCall();  // outputs "Hey there"
}

这段代码有效,但是我想知道细节。doCall()似乎上溯造型funcToCall到类型(void (Boo::*)(void))(void (Base::*)(void))它似乎也将我的instance变量转换成Boo似乎魔术般地知道funcToCall我给I属于Boo并相应地进行转换。

这是怎么做的?这是在运行时还是编译时完成的?在调用时,它是否只是尝试查找函数的名称(instance->*funcToCall)();

而且不要挑剔我typedef我知道有些东西需要typedef可读性。这只是测试代码。

编辑:我玩了更多的代码,这似乎很陌生。我添加了一个新类,这是结果:

class Goo : public Base
{
public:
    void callingFunc()
    {
        cout << "Yo there" << endl;
    }
};

void main()
{
    Foo * foo = new Foo();
    Boo * boo = new Boo();
    Goo * goo = new Goo();

    foo->setCallback(goo, selector(Boo::callingFunc) );
    foo->doCall(); // outputs "Hey there" not "Yo there"
}

在这一点上,这是有道理的,但也没有道理。我的意思是,很明显它将在Boo中调用“ Hey There”,但是为什么代码不会爆炸?看起来很危险。

编辑2:发现确实令人不安和不安的东西。我调整了代码,以便接受一个计数器,以便我有一个变量来检查正在发生的事情。

#include <iostream>

using namespace std;

class Base
{
};

typedef void(Base::*handler)();
#define selector(_SELECTOR) static_cast<handler>(&_SELECTOR)

class Boo : public Base
{
public:
    Boo() : counter(0) {}
    void callingFunc()
    {
        cout << "Hey there " << counter << " at " << &counter << endl;
        counter += 1;
    }

    int counter;

};

class Goo : public Base
{
public:
    Goo() : counter(0) {}
    void callingFunc()
    {
        cout << "Yo there " << counter << " at " << &counter << endl;
        counter += 1;
    }

    int counter;
};

class Foo
{
public:
    void setCallback( Base * instance,  void (Base::*funcToCall)(void) )
    {
        this->instance = instance;
        this->funcToCall = funcToCall;
    }

    void doCall()
    {
        (instance->*funcToCall)();
    }

private:
    Base* instance;
    void (Base::*funcToCall)(void);
};

void main()
{
    Foo * foo = new Foo();
    Boo * boo = new Boo();
    Base * base = new Base();
    Goo * goo = new Goo();

    // first run
    foo->setCallback(goo, selector(Boo::callingFunc) );
    foo->doCall(); // "Hey there 0 at 0044BC60"

    foo->setCallback(boo, selector(Boo::callingFunc) );
    foo->doCall(); // "Hey there 0 at 0044BC00"

    //second run
    foo->setCallback(goo, selector(Boo::callingFunc) );
    foo->doCall(); // "Hey there 1 at 0044BC60"

    foo->setCallback(boo, selector(Boo::callingFunc) );
    foo->doCall(); // "Hey there 1 at 0044BC00"

    // attempt with base
    foo->setCallback(base, selector(Boo::callingFunc) );
    foo->doCall(); // "Hey there *rubbish number* at  at 0044BC30"

}

现在我很确定函数回调是运行时的事情(显然是因为它不会产生编译错误,但是我不确定,因为通常情况并非如此)。如果它是运行时的东西,那么是的,因为它的工作原理几乎类似于脚本语言(按变量名查找变量,如果存在则对其进行更新,等等),这是有意义的。

我仍然需要有人确认。同时看起来确实强大而危险。自从我看到这样的东西以来已经有一段时间了。我现在太忙了,无法尝试打开组装的东西来解释正在发生的事情。另外,我不擅长阅读^^ ;;

编辑3谢谢大家,这一切现在都有意义。villekulla的答复使我相信,由于我的Boo和Goo类的结构相同,因此可以以相同的方式访问“计数器”变量(如果您了解类和结构的内存是如何分配的,这很明显)。所以我在Goo插入了一个'char'变量:

class Goo : public Base
{
public:
    Goo() : counter(0) {}
    void callingFunc()
    {
        cout << "Yo there " << counter << " at " << &counter << endl;
        counter += 1;
    }

    char hey;
    int counter;
};

致电:

foo->setCallback(goo, selector(Boo::callingFunc) );
foo->doCall();

两次将产生乱码,因为它抓住了计数器应放在的字符(确认未定义的行为,如前所述)。没有编译错误,因为……就编译而言,代码没有什么大不了的。

再次感谢!

维尔库拉

这是未定义的行为。

考虑将成员添加到Foo和Goo中,并调整callingFunc以使用该成员:

class Boo : public Base
{
public:
  Boo()
    : m("Boo")
  {}
  void callingFunc()
  {
     cout << "Hey there, I'am " << boo << endl;
  }
  const char* m;
};

class Goo : public Base
{
public:
  Goo()
    : m("Goo")
  {}
  void callingFunc()
  {
     cout << "Yo there, I'am " << goo << endl;
  }
  const char* m;
};

在这种情况下

foo->setCallback(boo, selector(Boo::callingFunc) );

你得到的输出

嘿,我是Boo

而在这种情况下

foo->setCallback(goo, selector(Boo::callingFunc) );

你得到的输出

嘿,我是Goo

您清楚地看到Boo :: callingFunc得到了Goo的支持...

这是C ++如何帮助脚步射击的数百万个例子之一...仅做标准允许的事情:/

您的示例并未爆炸,因为调用Func和Goo / Foo无关紧要。而且,如果不幸的是它永远不会爆炸,那么它“只会”会引入奇怪的错误(Foo :: callingFunc处理Goo :: callingFunc的数据)。

因为您没有使用虚函数,所以所有函数调用地址都在获取地址时在编译时解析(在foo-> setCallback(boo,selector(Boo :: callingFunc))行中);

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何像正常的C函数一样使用正确的“ this”指针调用C ++类成员函数?(指向类成员函数的指针)

来自分类Dev

在类定义C ++之前使用类成员函数指针

来自分类Dev

如何使用函数更新c ++类成员?

来自分类Dev

指向类成员的 C++ 函数指针

来自分类Dev

成员函数指针c ++

来自分类Dev

c ++ 11 Thread类如何使用类成员函数

来自分类Dev

c ++ 11 Thread类如何使用类成员函数

来自分类Dev

C ++:如何调用属于同一类成员的成员函数指针?

来自分类Dev

FSM在C ++中使用成员函数指针

来自分类Dev

C ++外部函数,带有指向函数作为参数的指针,在带有成员函数的类内部使用

来自分类Dev

C ++:如何重载函数,使其可以使用任何函子,包括指向成员函数的指针?

来自分类Dev

C ++:如何将指针传递给另一个类的成员函数?

来自分类Dev

C ++如何将成员函数指针传递给另一个类?

来自分类Dev

如何获得通用函数指针作为C ++类的私有成员?

来自分类Dev

来自其他类的C ++成员函数指针

来自分类Dev

C ++-无法修改类成员函数中的指针

来自分类Dev

C++:调用成员函数时在指针向量中无效使用抽象类

来自分类Dev

调用成员指针函数C ++

来自分类Dev

C ++成员函数指针定义

来自分类Dev

调用成员指针函数C ++

来自分类Dev

C ++如何使函数指针指向类方法

来自分类Dev

指向成员函数的C ++指针出错:不是函数或函数指针

来自分类Dev

如何将(非静态成员函数的)C ++函数指针传递给预定义的C函数?

来自分类Dev

C ++:如何返回指向非静态成员函数的指针?

来自分类Dev

使用成员函数指针作为键的C ++映射问题

来自分类Dev

如何使用基类的数据成员作为派生类的构造函数?(在 C++ 中)

来自分类Dev

C ++指向具有匹配函数签名的任何类的成员函数的指针

来自分类Dev

C ++ typedef函数定义为类成员,以后用作函数指针吗?

来自分类Dev

C ++是否有定义的方法将指针传递给类的成员对象的成员函数?

Related 相关文章

  1. 1

    如何像正常的C函数一样使用正确的“ this”指针调用C ++类成员函数?(指向类成员函数的指针)

  2. 2

    在类定义C ++之前使用类成员函数指针

  3. 3

    如何使用函数更新c ++类成员?

  4. 4

    指向类成员的 C++ 函数指针

  5. 5

    成员函数指针c ++

  6. 6

    c ++ 11 Thread类如何使用类成员函数

  7. 7

    c ++ 11 Thread类如何使用类成员函数

  8. 8

    C ++:如何调用属于同一类成员的成员函数指针?

  9. 9

    FSM在C ++中使用成员函数指针

  10. 10

    C ++外部函数,带有指向函数作为参数的指针,在带有成员函数的类内部使用

  11. 11

    C ++:如何重载函数,使其可以使用任何函子,包括指向成员函数的指针?

  12. 12

    C ++:如何将指针传递给另一个类的成员函数?

  13. 13

    C ++如何将成员函数指针传递给另一个类?

  14. 14

    如何获得通用函数指针作为C ++类的私有成员?

  15. 15

    来自其他类的C ++成员函数指针

  16. 16

    C ++-无法修改类成员函数中的指针

  17. 17

    C++:调用成员函数时在指针向量中无效使用抽象类

  18. 18

    调用成员指针函数C ++

  19. 19

    C ++成员函数指针定义

  20. 20

    调用成员指针函数C ++

  21. 21

    C ++如何使函数指针指向类方法

  22. 22

    指向成员函数的C ++指针出错:不是函数或函数指针

  23. 23

    如何将(非静态成员函数的)C ++函数指针传递给预定义的C函数?

  24. 24

    C ++:如何返回指向非静态成员函数的指针?

  25. 25

    使用成员函数指针作为键的C ++映射问题

  26. 26

    如何使用基类的数据成员作为派生类的构造函数?(在 C++ 中)

  27. 27

    C ++指向具有匹配函数签名的任何类的成员函数的指针

  28. 28

    C ++ typedef函数定义为类成员,以后用作函数指针吗?

  29. 29

    C ++是否有定义的方法将指针传递给类的成员对象的成员函数?

热门标签

归档