覆盖所需的反差方法

ela*_*dan 4 c++ virtual overriding covariance contravariance

我很难找到(我确信这是一个非常常见的)设计模式来解决以下问题.考虑一下这段代码:

class AA {};
class BB : public AA {};

class A
{
public:
    virtual void foo(AA& aa) = 0;
};

class B : A
{
public:
    void foo(BB& bb){cout<<"B::foo"<<endl;}
};

int main()
{
    B b;
    BB bb;
    b.foo(bb);
}
Run Code Online (Sandbox Code Playgroud)

此代码将无法编译,因为类B不会覆盖纯虚函数'foo'.编译器认为B声明的foo仅作为foo的重载,因为覆盖函数中的输入参数中不允许使用协方差.

现在,我明白了这个的原因.B继承自A的事实意味着它应该能够使用类型AA的参数处理对foo的任何调用,并且前面的代码没有给出任何实现来处理除BB之外的任何参数类型.

当然我可以在B的foo实现中将aa转换为BB,但我正在寻找一种保留类型安全性的解决方案,并且实际上迫使B类的实现者也实现了一个继承自AA的类以便代码编译.在一个理想的世界里,我可以编写一些看起来像这个伪代码的东西:

class A
{
public:
    abstract class AA{}; //indicates that any child of A must implement also child of AA
    abstract void foo(AA& aa);
};

class B : public A
{
public:
    class BB : AA{}; //will not compile without this
    void foo(BB& bb){cout<<"B::foo"<<endl;}
};
Run Code Online (Sandbox Code Playgroud)

有没有办法在C++中实现类似的东西?(可能通过某种映射对象来增强,而不需要继承)

请注意,实际上(与示例中不同),BB和AA之间的继承是至关重要的,因为AA有许多孩子具有许多品质,最后我想要完成的是迭代A类的向量并运行' foo'只有适当的参数(AA的矢量)

gre*_*rep 8

要提供类型安全性,您应该使用模板而不是继承.

class AA {};
class BB : AA {};

template <typename Managed> class FooManager {
    virtual void foo(Managed& m) { /* default implementation */ }
};

class B : public FooManager<BB> {
    void foo(BB bb) { cout << "B:foo()" << endl; }
};
Run Code Online (Sandbox Code Playgroud)

稍后在代码中,例如,如果要遍历数组,

template<typename Managed> void processAll(vector<Managed> v, FooManager<Managed> mgr) {
    for(Managed& m : v) mgr.foo(m);
}

B b;
vector<BB> bbs;
processAll(bbs, b);
Run Code Online (Sandbox Code Playgroud)

编辑:拼写错误修复