我有一个基本的问题,就是要了解ostream究竟是什么。我知道它是输出流的基类,但是在使用它时我不能非常喘息,为什么要使用它而不是仅仅说std :: cout。 所以这里我有这个例子,我必须用pop()函数创建一个名为stack的新类(就像在C ++中已经提供的类一样)。
这里list_node是一个由两个元素组成的结构:键(一个整数)和一个指向下一个整数的指针。
list_node的定义(已经给出):
struct list_node {
int key;
list_node∗ next;
// constructor
list_node (int k, list_node∗ n)
: key (k), next (n) {}
};
以下是该类的定义(已经给出):
class stack {
public:
void push (int value) {...}
...
private:
list_node∗ top_node;
};
这是我遇到问题的部分:
void print (std::ostream& o) const
{
const list_node* p = top_node;
while (p != 0) {
o << p->key << " "; // 1 5 6
p = p->next;
}
}
我不明白为什么他们使用ostream&amp; amp; o作为函数参数。难道他们不能将top_node作为参数并使用它上面的.next函数(.next读取下一个list_node)然后他们可以用std :: cout函数打印它。为什么以他们这样做的方式做得更好?
答案 0 :(得分:0)
为什么以他们这样做的方式做得更好?
我不确定你的问题,也不确定这是一个更好的方法。
也许意图是灵活性。以下是我的应用程序库中的示例:
当我将数据属性声明为ostream
时class T431_t
{
// ...
std::ostream* m_so;
// ...
我可以简单地使用该属性向'where-m_so-points'发送报告。在这个应用程序中,有几个* mso&lt;&lt; ... 正在使用。这是主要的例子。
inline void reportProgress()
{
// ...
*m_so << " m_blk = " << m_blk
<< " m_N = 0x" << std::setfill('0') << std::hex << std::setw(16) << m_N
<< " " << std::dec << std::setfill(' ') << std::setw(3) << durationSec
<< "." << std::dec << std::setfill('0') << std::setw(3) << durationMSec
<< " sec (" << std::dec << std::setfill(' ') << std::setw(14)
<< digiComma(m_N) << ")" << std::endl;
// ...
}
请注意,在类构造函数(ctor)中,m_so有一个默认的赋值给std :: cout。
T431_t(uint64_t maxDuration = MaxSingleCoreMS) :
// ..
m_so (&std::cout), // ctor init - default
// ..
{
// ...
当用户选择双线程处理选项(这是一个命令行选项,通过使用我的桌面的两个处理器在大约1/2的时间内执行应用程序)时,如果我允许,报告将变得难以阅读两个独立的输出流交织在一起(在用户屏幕上)。因此,在由线程2运行的对象实例中,m_so被设置为不同的东西。
以下数据属性捕获并保存线程2输出,以便以后流式传输到std :: cout。
std::stringstream m_ssMagic; // dual threads use separate out streams
启动线程2并且线程将其设置为私有m_so:
void exec2b () // thread 2 entry
{
m_now = Clock_t::now();
m_so = &m_ssMagic; // m_so points to m_ssMagic
// ...
m_ssMagic << " execDuration = " << m_ssDuration.str()
<< " (b) " << std::endl;
} // exec2b (void)
虽然线程1使用std :: cout,而线程2使用m_ssMagic,但'main'(线程0)只是等待连接。
连接协调线程完成,通常大约在同一时间。 Main(线程0)然后cout是m_ssMagic内容。
//...
// main thread context:
case 2: // one parameter: 2 threads each runs 1/2 of tests
{ // use two new instances
T431_t t431a(MaxDualCoreMS); // lower test sequence
T431_t t431b(MaxDualCoreMS); // upper test sequence
// 2 additional threads started here
std::thread tA (&T431_t::exec2a, &t431a);
std::thread tB (&T431_t::exec2b, &t431b);
// 2 join's - thread main (0) waits for each to complete
tA.join();
tB.join();
// tA outputs directly to std::cout
// tB captured output to T431_t::m_ssMagic.
// both thread 1 and 2 have completed, so ok to:
std::cout << t431b.ssMagicShow() << std::endl;
retVal = 0;
} break;
完成,这是
std::string ssMagicShow() { return (m_ssMagic.str()); }
摘要
我首先编写了单线程应用程序。在完成这项工作后,我搜索了一种“简单”的方式来使用我桌面上的第二个核心。
作为我的第一个重构的一部分,我a)添加了“std :: ostream m_so”初始化为&amp; std :: cout,并且b)发现了std :: cout的所有用法。其中大多数我只是用“* m_so”代替。然后我c)确认我没有破坏单线程解决方案。非常简单,并且第一次尝试。
后续工作实现了命令行'双线程'选项。
我认为当预算允许时,这种方法将适用于我的下一个桌面。
从OOP的角度来看,这种努力是有效的,因为std :: ostream在std :: cout和std :: stringstream的类层次结构中。因此
"std::cout is-a std::ostream",
和
"std::stringstream is-a std::ostream".
因此m_so可以指向派生类的实例,并向任一目的地提供虚拟方法'ostream-access'。