对c ++中类中typedef函数的疑问 [英] Doubts about typedef functions inside a class in c++

查看:141
本文介绍了对c ++中类中typedef函数的疑问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



假设我有一个叫做dog的类(在.h中的类声明和在。 CPP),当狗死亡时,我想调用一个函数让狗经理知道。在狗的SetFunc中,我将收到要调用的函数:

Dog.h

  class Dog 
{
public:

typedef void(* OndogDie)(Dog * dog);

OndogDie函数;

void SetFunc(OndogDie func);
void Die();
};

Dog.cpp

  void Dog :: SetFunc(Dog :: OndogDie func)
{
function = func;
}

void Dog :: Die()
{
function(this);
}

如果我把classdef放在类Dog里面,类,它不能作为参数传递给狗类的适当回调:

Manager.h



<$ p







$ Manager $($)
void CbdogDie(Dog * dog);
};

Manager.cpp

  void Manager :: CbdogDie(Dog * d)
{
// stuff
}

Manager :: Manager()
{
Dog d = Dog();
d.SetFunc(CbdogDie); (错误:类型为void(Manager :: *)的参数(Dog * d)与类型为Dog :: OndogDie的参数不兼容)
}

我已经浏览了许多教程并回答了问题,但没有一个能够帮助我找出我的代码出了什么问题。我也考虑过使用委托类型,但它只能在一个clr项目中工作。



我认为问题可能出在我放置typedef的地方功能。还有其他地方可以定义这个功能吗?如果没有解决这个问题的方法,或者至少有其他解决方案。



谢谢

解决方案重复我的评论以方便其他读者: CbdogDie (在您的代码中)是一个函数成员(非静态),并且需要一个 Manager 的实例将被调用,因此它的类型与您的回调不兼容 typedef



与您的错误无关,但仍值得考虑:您是否不应该将调用回调的逻辑移动到 Dog 的析构函数中?在C ++中(例如与Java不同),我们知道什么时候我们的对象被销毁了。



不知道你是否可以将它应用到你的实际问题上,但这里有一些例子可以工作。

#include< iostream>
#include< string>

class Dog
{
public:

typedef void(* on_dog_die_callback_t)(const Dog&);

Dog(const std :: string& name,on_dog_die_callback_t callback):
name_(name),callback_(callback)
{
std :: clog< < 一只名为<< this-> getName()<< 出生。
}

〜Dog()
{
std :: clog<< 一只名为<< this-> getName()<< 已经死了。
if(this-> callback_)//允许NULL指针为空操作
this-> callback _(* this);
}

std :: string
getName()const
{
return this-> name_;
}

private:

std :: string name_;
on_dog_die_callback_t callback_;
};

//注意:这是一个免费的功能,不是班级成员。
void
friendly_callback(const Dog& dog)
{
std :: clog<< 我们很抱歉,<< dog.getName()<< 死了。
}

结构管理器
{
//注意:这是一个静态函数。
static void
unfriendly_callback(const Dog& dog)
{
std :: clog<< 哈哈,< dog.getName()<< 死了。
}
};


main()
{
Dog fido(Fido,friendly_callback);
狗莱卡(Leika,经理:: unfriendly_callback);
Dog waldo(Waldo,0);
}

运行此代码的输出为:

一只名为Fido的新狗诞生了。
名叫莱卡的新狗诞生了。
名为沃尔多的新狗诞生了。
名叫沃尔多的狗已经死亡。
一只名叫莱卡的狗已经死亡。
哈哈,莱卡去世了。
名为Fido的狗已经死亡。
菲多死了我们很抱歉。

请注意,我已经(不需要)将回调的签名更改为接受 const 引用一个 Dog 而不是指针。这通常会被认为是更好的风格,但如果您需要 指向任何我看不到的原因,您也可以做到这一点。



注意:如果您决定从析构函数调用回调,请注意有一些不寻常的事情需要注意:


  • 尽早在析构函数中调用回调。如果您的 Dog 类拥有在调用回调之前在destuructor中释放的资源,您将传递 this 指针指向一个部分被破坏的对象,并调用其上的任何成员函数都可能调用未定义的行为。
  • 回调函数不得调用任何 virtual Dog 的函数成员被传递。请注意, Dog 的析构函数只会在派生类的析构函数(如果有的话)之后调用,因此它可能会处理已经部分析构的目的。只要回调只对 Dog base感兴趣,这就好,但如果它试图访问派生类的任何成员(通过



好消息:如果你的类很简单(没有 virtual 函数,在析构函数中没有显式的资源释放),你会好的。


I need to define a function which will return an object of a class.

Suppose I have a class called dog (class declaration in .h and implementation in .cpp), and when the dog dies, I want to call a function to let the dog manager know that. In dog`s SetFunc I will receive the function to be called:

Dog.h

class Dog
{
public:

    typedef void (*OndogDie)(Dog * dog);

    OndogDie function;

    void SetFunc(OndogDie func);
    void Die();
};

Dog.cpp

void Dog::SetFunc(Dog::OndogDie func)
{
    function = func;
}

void Dog::Die()
{
    function(this);
}

If I put the typedef inside the class Dog, everthing works, execept the Manager class, which can`t pass as parameter a suitable callback for the dog class :

Manager.h

#include "Dog.h"

class Manager
{
public:
    Manager();
    void CbdogDie(Dog * dog);
};

Manager.cpp

void Manager::CbdogDie(Dog * d)
{
    //stuff
}

Manager::Manager()
{
    Dog d = Dog();
    d.SetFunc(CbdogDie); (Error: argument of type void(Manager::*)(Dog *d) is incompatible with parameter of type "Dog::OndogDie")
}

I already looked in many tutorials, and answered questions, but none of them had helped me find out what is wrong with my code. I have also considered using the delegate type, but it only worked in an clr project.

I`m thinking that the problem might be in the place where I put the typedef function. Is there any other place to define this function ? If not is there any solution to this problem, or at least an alternative to it.

Thanks

解决方案

Repeating my comment for the convenience of further readers: CbdogDie (in your code) is a function member (non-static) and requires an instance of Manager to be called so its type is incompatible with your callback typedef.

Unrelated to your error but still worth consideration: Shouldn't you move the logic that invokes the callback into Dog's destructor? In C++ (unlike Java, for example) we know when our objects are destructed.

Not sure if you can apply this to your actual problem but here are some examples that work.

#include <iostream>
#include <string>

class Dog
{
public:

  typedef void (* on_dog_die_callback_t)(const Dog&);

  Dog(const std::string& name, on_dog_die_callback_t callback) :
    name_(name), callback_(callback)
  {
    std::clog << "A new dog named " << this->getName() << " is born.\n";
  }

  ~Dog()
  {
    std::clog << "A dog named " <<  this->getName() << " has died.\n";
    if (this->callback_)  // allow NULL pointer for no-op
      this->callback_(*this);
  }

  std::string
  getName() const
  {
    return this->name_;
  }

private:

  std::string name_;
  on_dog_die_callback_t callback_;
};

// Note: This is a free function, not a class member.
void
friendly_callback(const Dog& dog)
{
  std::clog << "We are so sorry that " << dog.getName() << " died.\n";
}

struct Manager
{
  // Note: This is a static function.
  static void
  unfriendly_callback(const Dog& dog)
  {
    std::clog << "Haha, " << dog.getName() << " died.\n";
  }
};

int
main()
{
  Dog fido("Fido", friendly_callback);
  Dog leika("Leika", Manager::unfriendly_callback);
  Dog waldo("Waldo", 0);
}

The output of running this code is:

A new dog named Fido is born.
A new dog named Leika is born.
A new dog named Waldo is born.
A dog named Waldo has died.
A dog named Leika has died.
Haha, Leika died.
A dog named Fido has died.
We are so sorry that Fido died.

Note that I have (without need) changed the signature of your callback to accept a const reference to a Dog rather than a pointer. This will generally be considered better style but if you need a pointer for whatever reason I cannot see, you can do it as well.

Notice: If you decide to invoke the callback from your destructor, be aware that there are some unusual things to watch out for:

  • Invoke the callback early in your destructor. If your Dog class owns resources that are freed in the destuructor before the callback is invoked, you will pass a this pointer that points to a partially destructed object and calling any member function on it will likely invoke undefined behavior.
  • The callback must not invoke any virtual function members of the Dog it is passed. Note that Dog's destructor will only be called after the destructor of a derived class (if any) so it might deal with an already partially destructed object. As long as the callback is only interested in the Dog base, this is fine, but if it tries to access any members of the derived class (via virtual function calls), undefined behaviour will result.

The good news: If your class is simple (no virtual functions, no explicit resources released in the destructor), you'll be just fine.

这篇关于对c ++中类中typedef函数的疑问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆