【发布时间】:2011-08-22 08:38:05
【问题描述】:
我很难找到(我确信这是一种非常常见的)设计模式来解决以下问题。考虑这段代码:
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”
【问题讨论】:
-
您打算按值传递多态对象吗?你会遇到切片问题......你应该通过
AA& aa和BB& bb -
为什么
foo在这种情况下必须是虚拟的? -
@Andreas:我希望所有从 A 继承的类都必须实现自己的 foo 版本,因此它是纯虚拟的
-
你可能希望你的所有继承都是
public,而不是(隐式)private。否则你的问题将没有意义,例如BB&不会隐式转换为AA&,如果没有特殊访问权限,您不能将AA&向下转换为BB&。
标签: c++ overriding virtual covariance contravariance