在C++中转换函数指针

3

假设我有两个类,A和B:

class A
{
public:
    typedef void (*Handler)( A * a );

    Handler handler;

    void foo() ( handler( this ); }
};

class B : public A
{
};

假设我有一个函数
void bar( B * b );

我能否继续进行

B b;
b.handler = bar;???

如果我声明 void bar( A * a ) ,那么一切都很好,但是我必须将a强制转换为一个B*,这很丑陋。我不能将typedef用作模板,所以有没有一种更好的方法呢?


3
没有一种优雅的方法来做这件事。这个论点不是协变的;试图将其视为协变的将不可避免地变得丑陋,这是有充分理由的。 - R. Martinho Fernandes
3
如果你想要这种类型的多态性,看起来你需要使用 CRTP(Curiously Recurring Template Pattern)... - cdhowie
3个回答

4

不,没有。

你正在违反LSP原则:b.handler()不能被任意的A*调用,而基类却保证能够调用。

B b;
b.handler = bar; // This doesn't compile!
A a2;
b.handler(&a2); // As this would call bar(B*) with an A*

在这种情况下可能会有不同的类型,但仅当参数是反变的并且返回值是协变的时才可以。


1
这是cdhowie提到的解决方案。您可以定义一个抽象基类:
template<typename T>
class AbstractA {
   typedef void (*Handler)( T * a );
   Handler handler;

   void foo() ( handler( (T*) this ); }
};

然后像这样实现子类:
class A : public AbstractA<A> {
    //...
};

class B : public AbstractA<B> {
    //...
};

0

这似乎是虚函数的工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接