需要覆盖逆变解决方法
我很难找到(我确信这是一个非常常见的)设计模式来解决以下问题。考虑这段代码:
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);
}
这段代码将无法编译,因为类 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;}
};
有没有办法在 C++ 中实现类似的功能? (也许可以通过某种映射对象来提升,而不需要继承)
请注意,实际上(与示例中不同),BB 和 AA 之间的继承至关重要,因为 AA 有许多具有许多共同品质的子代,最后是什么我想要完成的是迭代 A 类的向量并仅使用适当的参数(AA 的向量)运行“foo”
I'm having difficulty finding the (what I'm sure is a very common) design pattern to work around the following problem. Consider this piece of code:
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);
}
This code will not compile because the class B does not override the pure virtual function 'foo'. The compiler considers the foo that B declares only as an overload to foo because co-variance is not allowed in input parameters in overriden functions.
Now, I understand the reason for this. The fact that B inherits from A means that it should be able to handle any calls to foo with parameters of type AA, and the previous code gave no implementation to handle any parameter type except BB.
Of course I could just cast the aa to BB in B's foo implementation, but I'm looking for a solution that preserves type-safety and actually forces the implementer of B class to also implement a class that inherits from AA in order for the code to compile. In an ideal world I would be able to write something that looks like this pseudo-code:
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;}
};
Is there a way to achieve something similar to this in C++? (boost maybe, by some kind of mapping object without the need for inheritance)
Please note that in actuality (unlike in the example), inheritance between BB and AA is crucial as AA has many children that share many qualities, and in the end what I want to accomplish is to iterate over a vector of A classes and run 'foo' only with appropriate parameters (vector of AA's)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了提供类型安全,您应该使用模板而不是继承。
稍后在代码中,例如,如果要遍历数组,请
编辑:拼写错误修复
To provide type safety, you should use templates instead of inheritance.
Later in the code, for example, if you want to traverse an array,
Edit: typo fix
你可以看看访客模式。这是“双重调度”类型问题的一般解决方案(根据对象和消息调度到虚拟函数)。
也就是说,将
foo()
放入访问者中,并将A::foo()
重命名为A::Visit(FooVisitor& )
:编辑:澄清一下,这可能有助于理清层次结构的目的。如果您仔细想想,您正在尝试根据另一个层次结构(
A
和AA
和BB
)对一个层次结构的关系进行建模。代码>B)。这对于建模来说非常尴尬,甚至从概念上思考也是非常尴尬的。要将其重新建模为访问者,您通常会将其中一个层次结构转换为单个类,然后对可以通过访问者在算法层次结构中对该类执行的操作进行建模。这更加健壮,因为它强制您显式实现层次结构关系的每个组合,并且如果您稍后修改层次结构,则会在编译时中断(很好)。
you could look at the visitor pattern. this is the general solution to 'double dispatch' type problems (dispatch to a virtual function based on the object and the message).
That is, put
foo()
into a visitor, and renameA::foo()
toA::Visit(FooVisitor& )
:edit: to clarify, it might help to disentangle the purposes of your hierarchies. If you think about it, you are trying to model the relationship of one hierarchy (
AA
andBB
) in terms of another (A
andB
). This is pretty awkward to model, or even to think about conceptually.To remodel this as a visitor, you'd generally turn one of the hierarchies into a single class, and instead model the operations you can perform on that class in a hierarchy of algorithms via a visitor. This is more robust because it forces you to explicitly implement each combination of hierarchy relationships, and will break at compile-time (good) if you modify the hierarchy later on.