我有一个类向量,我想在屏幕上显示各自的参数。每个类都继承自CBase
,而vector只是一个类型为CBase
的指针列表。
我想避免将显示代码耦合到类。因此,我将流运算符放在类定义之外。
所以我的课程被定义为
class CBase
{
public:
virtual ~CBase(){}
};
class CChildA : public CBase
{
};
class CChildB : public CBase
{
};
并且矢量设置如下:
void main()
{
CChildA A;
CChildB B;
std::vector<CBase*> myList;
myList.push_back(&A);
myList.push_back(&B);
display(myList);
}
并且各个显示操作符可能是:
std::ostream & operator<<(std::ostream & os, const CChildA & item)
{
os << "Child A Values Here";
return os;
}
std::ostream & operator<<(std::ostream & os, const CChildB & item)
{
os << "Child B Values Here";
return os;
}
要实现display
函数,我们遇到了问题,因为<<
不会选择正确的类,并且并非所有类都有一个流运算符定义(例如,类CChildC
没有这里显示)。因此,首次展示可能是:
void display(std::vector<CBase*> &aList)
{
for(std::vector<CBase*>::iterator it = aList.begin(); it != aList.end(); it++)
{
if(CChildA * ca = dynamic_cast<CChildA*>(*it))
std::cout << *ca << "\n";
else if(CChildB * cb = dynamic_cast<CChildB*>(*it))
std::cout << *cb << "\n";
}
}
但我被告知使用dynamic_cast
不赞成。是否有一种简单的方法可以在没有dynamic_cast
的情况下实现这一目标?
答案 0 :(得分:1)
此时我不得不问你,
所有派生类都应该实现流操作吗?
如果对此的答案是&#39;是的&#39;或者&#39;当然!&#39;,那你为什么不把它作为界面的一部分呢?
是的,您现在可以支持将对象打印到流中。但是,你只是自己说,它是所有衍生类必须拥有的属性。
让我们想到另一个问题 -
如果我要添加新的派生类,代码中的其他位置是否会发生变化?
嗯......当然,但这些应该是微小的变化。您不想更改使用流媒体运营商的每个地方。这将违反OCP - Open Close Principle。
关于这个 -
我想避免将显示代码耦合到类。因此,我将流运算符放在类定义之外。
你要么:
如果每个派生类都应该是可显示的,并且持有数据的容器应该显示每个元素 - 只需将相关方法添加到Base类。
如果你的大多数代码与显示代码无关,并且这些类确实与显示机制无关 - 每个派生类应该可以从两个接口继承(纯抽象类)
Base
类IDisplayable
(按照您的意愿命名)您展示的展示方法应该会收到vector<IDisplayable*>
而不是vector<Base*>
。
注意强>
如果你被迫接受vector<Base*>
,你应该迭代元素并将它们转换为IDisplayable*
(static_cast
或dynamic_cast
,这实际上取决于你的情况)
这与您当前的解决方案不同,因为您只需要一次演员(而不是为每个派生类设置演员表)
<强>注2 强>
我不是超载“#&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&#和&#39;&gt;&gt;&#39;运营商。我会考虑一个名为&#39; display&#39;的纯虚函数。在界面而不是虚拟运算符。