C++ 继承类中的回调参数类型不匹配
我正试图根据顶部答案中的链接代码实现一个事件管理器: 然而,当我尝试注册回调时,我得到了一个错误。 我肯定它与typedef有关,我承认我不确定它到底是如何工作的,但它在链接代码中的形式是完全相同的。 B类应该是从接口继承的,那么为什么类型不同呢? 我已将代码压缩为下面的最小示例C++ 继承类中的回调参数类型不匹配,c++,callback,arguments,inherited,C++,Callback,Arguments,Inherited,我正试图根据顶部答案中的链接代码实现一个事件管理器: 然而,当我尝试注册回调时,我得到了一个错误。 我肯定它与typedef有关,我承认我不确定它到底是如何工作的,但它在链接代码中的形式是完全相同的。 B类应该是从接口继承的,那么为什么类型不同呢? 我已将代码压缩为下面的最小示例 #include <iostream> class Interface; typedef void (Interface::*Callback)(void *data); class Interfac
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
void Register (Callback func);
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
{
Register( (Callback)Echo );
}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
int main()
{
B b;
return 0;
}
谁能解释一下我做错了什么?
谢谢我认为您最好使用std::function(c++11)或boost::function(c++03+boost) 这不是Java,接口不是语言定义的东西。这样,您就可以拥有一个接口,您可以选择实现哪个部分,如果回调与您的类无关,那么就不要实现它 void*不好的原因有很多。从C++ FAQ 避免void*(将它们放在低级函数和数据结构中 如果您真的需要它们并提供类型安全接口,通常 模板(适用于您的用户) 搜索“void*” <>但基本上空隙*绕过了C++加入的所有类型安全性。这是对C语言的一种攻击,以弥补它没有任何多态性或泛型代码的事实。正如正确指出的那样,
Echo
不是接口的成员,因此B::Echo
不符合接口::*回调
。但您可以使用模板来实现这一点,例如:
template <class T> class Interface {
public:
typedef void (T::*Callback)(void *data);
void Register(Callback func) {
std::cout << "Register" << std::endl;
}
// ...
};
class B : public Interface<B> {
public:
B() {
Register(&B::Echo);
}
void Echo(void *data) {
// Do something
}
};
模板类接口{
公众:
typedef void(T::*回调)(void*数据);
无效寄存器(回调函数){
STD::你没有一个函数<代码>接口::回声< /代码>,简单的说……你可能想考虑使用<代码> Boo::函数< /C>或等效工具……我认为使用模板将是最好的解决方案。我不知道我连接的代码是如何工作的,也许它不:PI不能使用虚拟,因为每次回调。对于每个继承的类,都需要在接口类中实现。使用void*有什么危险?请阅读我在答复底部附加的内容。@Shootfast:避免void*
是一个很好的建议。主要原因是void*
可以隐式转换为任何不安全的指针类型,并且我不能给你一些调试时间。
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
std::function<void(void*)> register;
Interface(std::function<void(void*)> register_)
: register(register_) //intializer list
{}
virtual ~Interface(){} //put me in
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
: Interface( std::bind(B::Echo, this) )
{}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
class Interface
{
public:
virtual void Echo(void*)=0;
};
void B::Echo(void *data) //implements Echo
{
std::cout << "Echo" << std::endl;
}
class Interface
{
public:
virtual ~Interface(){} //put me in
virtual void echo(void*){} //if implementation is not extended it will do nothing.
//others
};
template <class T> class Interface {
public:
typedef void (T::*Callback)(void *data);
void Register(Callback func) {
std::cout << "Register" << std::endl;
}
// ...
};
class B : public Interface<B> {
public:
B() {
Register(&B::Echo);
}
void Echo(void *data) {
// Do something
}
};