我需要解决这个问题。 有一个基类和两个继承的类。基类包含需要函数指针作为参数的方法。但是这些函数是在继承的类中定义的。
class CBase;
typedef bool (CBase::*FPredicate)();
class CBase
{
public:
CBase() {}
~CBase() {}
protected:
//this method waits until 'predicate' is true or until 'timeout' ms. passed
//and returns true if 'predicate' is true eventually
bool WaitEvent(FPredicate predicate, int timeout)
{
bool result = false;
int time1 = GetTickCount();
int time2;
bool isEnd = false;
while(!isEnd)
{
result = isEnd = (this->*predicate)();
time2 = GetTickCount();
if(time2 - time1 > timeout && !isEnd)
isEnd = true;
}
return result;
}
};
class CChildA : public CBase
{
protected:
bool a1() {/*some work*/}
bool a2() {/*some work*/}
void a_main()
{
...
WaitEvent(&CChildA::a1, 100);
...
WaitEvent(&CChildA::a2, 100);
...
}
};
class CChildB : public CBase
{
protected:
bool b1() {/*some work*/}
bool b2() {/*some work*/}
void b_main()
{
...
WaitEvent(&CChildB::b1, 100);
...
WaitEvent(&CChildB::b2, 100);
...
}
};
MSVC 2005编译器在WaitEvent调用时出错:
错误C2664:'CBase :: WaitEvent':无法将参数1从'bool(__thiscall CChildA :: *)(void)'转换为'FPredicate'
问题是:如何更改代码才能使其正常工作?将WaitEvent调用重写为是否安全
WaitEvent((FPredicate)(&CChildA::a1), 100)
?
在这种情况下,编译器会说没有错误但是安全吗?或者有更好的方法来解决问题吗?
提前谢谢。
答案 0 :(得分:3)
问题是隐式传递它的类型不同。要么你投了它,但是在存在多重继承的情况下可能会失败。一个更好的&更强大的解决方案是将签名更改为:
template< typename T >
bool WaitEvent( bool ( T::*predicate )(), int timeout ) { ... }
答案 1 :(得分:3)
您可以使用模板类来关闭子对象及其函数成员,从而保存它的正确类型。然后使用虚函数让基类通过通常的多态来调用它。
在shared_ptr中使用类似的机制来调用析构函数。请参阅:http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n
#include <iostream>
struct CPredicateBase
{
virtual ~CPredicateBase() {}
virtual bool operator()() = 0;
};
template <class T>
struct CPredicate : public CPredicateBase
{
bool (T::*func)();
T* self;
CPredicate(T* self_, bool (T::*func_)())
: func(func_), self(self_) {}
bool operator() () { return (self->*func)(); }
};
class CBase
{
public:
bool WaitEvent(CPredicateBase& predicate, int imeout)
{
/// just to show the call
bool b = predicate();
std::cout << "WaitEvent called predicate() => " << b << std::endl;
return b;
}
};
class CChildA : public CBase
{
public:
bool a1() { return false; }
bool a2() { return true; }
void a_main()
{
std::cout << "CChildA::a_main()" << std::endl;
CPredicate<CChildA> caller1(this, &CChildA::a1);
bool ra1 = WaitEvent(caller1, 100);
CPredicate<CChildA> caller2(this, &CChildA::a2);
bool ra2 = WaitEvent(caller2, 100);
}
};
class CChildB : public CBase
{
public:
bool b1() { return false; }
bool b2() { return true; }
void b_main()
{
std::cout << "CChildB::b_main()" << std::endl;
CPredicate<CChildB> caller1(this, &CChildB::b1);
bool rb1 = WaitEvent(caller1, 100);
CPredicate<CChildB> caller2(this, &CChildB::b2);
bool rb2 = WaitEvent(caller2, 100);
}
};
int main(int argc, char const* argv[])
{
CChildA cA;
CChildB cB;
cA.a_main();
cB.b_main();
return 0;
}