我需要在外流上绘制我的对象,通常是cout
。
但我也希望用户能够输入具有<<
运算符的任何流(例如QTextStream
),因此每次都不必是cout
。
定义此类参数的最简单方法是什么?
所以这就是我想拥有的东西,这是可以比拟的东西:
virtual void draw(GeneralOutStream out = std::cout)
{
out << m_name << std::endl;
}
我知道我可以使用模板(这就是我正在做的事情。)但是我希望有一个不需要模板的解决方案。 但是,模板解决方案工作正常,所以基本上我只是好奇。
答案 0 :(得分:2)
我可以想到四种方法。
首先,将std::ostream
作为GeneralOutStream
,并假设每个人都从中继承。也许写一些包含QTextStream
的东西,使其成为std::ostream
。
其次,编写一个template
方法,该方法需要GeneralOutStream&& out
并对其进行操作。这需要在标题中公开您的实现。我推荐这个。相当强烈,但它确实意味着virtual
最终变得毫无用处。
第三,编写一个类型擦除GeneralOutStream
,它使用template
构造函数在类中公开要与之交互的通用输出流的部分,该构造函数将传递的泛型类型存储在{{ 1}}使用pImpl
方法,然后在对象的实现中使用该类型。这有运行时开销,编写非常棘手,并且类似于virtual
的模式 - 除了std::function
必须处理能够编写完整的无数类型!
如果我要编写#3,GeneralOutStream
将是GeneralOutStream
,它采用template
应该处理的一系列类型,然后进行一些元编程以准确显示那些重载到GeneralOutStream
。这非常棘手,因为您需要手动复制重载决策。
Forth,创建要支持的“GeneralOutStream”类型的枚举。使用双调度技术通过<<
方法调用传递对这些类型的实例的引用,在另一方面将它们分开并调用您的实现virtual
方法,要求实现类处理整个枚举。这个实现比#3稍微不那么棘手,限制了您可以传递给template
方法的类型,但允许完全访问实现draw
中的类型。
答案 1 :(得分:0)
您想要一个解决方案 stream (来自std::ostream
)或任何具有<<
运算符的对象吗?
在第一种情况下,您可以传递对流对象的引用:
virtual void draw(std::ostream& out = cout) {
out << m_name << std::endl;
}
传递副本不会编译。
在第二种情况下,主要问题是界面,因为它看起来你想要将该函数定义为虚拟成员。如果不是这种情况,并且您仍然需要任何对象的解决方案(不是必需的标准ostream
,而是任何定义了运算符<<
的解决方案),则必须使用模板