为了方便更多读者,重复我的评论: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 << "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);
}
运行这段代码的输出是:
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.
请注意,我已经(不需要)更改了您的回调的签名以接受const
参考一个Dog
而不是指针。这通常被认为是更好的风格,但如果你need无论出于何种原因我看不到一个指针,你也可以做到。
Notice:如果您决定从析构函数调用回调,请注意需要注意一些不寻常的事情:
- 在析构函数中尽早调用回调。如果你的
Dog
类拥有在调用回调之前在析构函数中释放的资源,您将传递一个this
指向部分破坏的对象的指针并调用其上的任何成员函数可能会调用未定义的行为。
- 回调不得调用任何
virtual
职能成员Dog
它已经通过了。注意Dog
的析构函数只会被调用after派生类的析构函数(如果有),因此它可以处理已经部分析构的对象。只要回调只对Dog
基类,这很好,但是如果它尝试访问派生类的任何成员(通过virtual
函数调用),将导致未定义的行为。
好消息:如果你的课程很简单(没有virtual
函数,析构函数中没有显式释放资源),你会没事的。