2012-01-10 92 views
2

我试图从派生类传递一个函数,它需要一个函数指针的基类函数,但我得到一个编译器错误。无法将派生类函数的指针传递到基类

[BCC32 Error] E2034 Cannot convert 'void (Bar::*)(int)' to 'void (Foo::*)(int)' 

我想这是按照设计,但有没有办法解决这个不涉及不愉快的铸造? boost::bind能帮助我吗?

#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) 

class Foo 
{ 
public: 
    typedef void (Foo::*FFunc)(int i); 

    void test(FFunc f) 
    { 
    CALL_MEMBER_FN(*this,f)(123); 
    } 

    void barf1(int i) {}; 
}; 

class Bar : public Foo 
{ 
public: 
    void barf2(int i) {}; 
}; 

void ffff() 
{ 
    Foo f; 
    f.test(Foo::barf1); // works 

    Bar b; 
    b.test(Bar::barf1); // works 
    b.test(Bar::barf2); // ERROR 
} 

作为一个方面说明,我这工作正常使用虚拟函数,这是显而易见的方法,而不是一个函数指针,但我只是想获得它在尝试一些刺激前的工作是这样的: :绑定挂羊头卖狗肉后...

+0

如果你有一个C++编译器11,也许你可以使用[' std :: function'](http://en.cppreference.com/w/cpp/utility/functional/function)和['std :: bind'](http://en.cppreference.com/w/ CPP /实用程序/功能/绑定)? – 2012-01-10 13:12:46

回答

1

b.test((Foo::FFunc)&Bar::barf2);

对不起,不是故意要提交的答案,想发表评论。 Sample code

编辑:嗯,也许这是更令人愉快的铸造,因为它是C++风格? Updated sample.

b.test(static_cast<Foo::FFunc>(&Bar::barf2));

+0

嗯,这是有效的。但这是我希望避免的“不愉快的投射”! – Roddy 2012-01-10 13:32:54

+0

@Roddy你可以使用'static_cast',这是完全有效的C++强制转换。我的意思是,我敢打赌'boost :: bind'在内部的某个地方使用这种类型的东西... – lapk 2012-01-10 13:38:08

+0

你确定这是有效的C++吗?从我记得将一个函数(或成员函数)指针转换为另一种类型然后尝试调用它是非法的。它可能在这种情况下工作,因为从'b'到'Foo *'(调用'test'时)可能是noop,但我认为这是不能保证的(如果多重或虚拟继承是参与)。 – Grizzly 2012-01-10 14:13:57

1

此外,正如我的C++ 11 & &博斯特的知识& & STL是不是最好的,我只能劝这样的:

template <typename T> 
    void test(void (T::*f)(int)) 
    { 
    CALL_MEMBER_FN(static_cast<T&>(*this),f)(123); 
    } 

所有其他代码相同,以你的。

坏铸造,但它隐藏

1

你可以概括函数指针多一点?我的意思是这样的:

typedef void (Foo::*FFunc)(int i); 

到:

typedef void (*FFunc)(int i); 

然后你可以使用绑定:

b.test(bind(&Bar::barf2, &b)); 
+1

不,你不能从'绑定'(我假设你的意思是'boost :: bind'或'std :: bind',否则请详细说明)返回一个函数对象而不是函数指针。 'typedef函数 FFunc;'应该可以工作(但当然有很多开销)。 ' – Grizzly 2012-01-10 14:09:30

+0

你说得对,我的错。我使用boost:函数,而不是函数指针。绑定将不会与指针一起使用。 – 2012-01-10 14:11:13

相关问题