2017-08-04 77 views
0

我对理解什么是ostream是一个基本问题。我知道它是输出流的基类,但是我不能很好地使用它,以及为什么要使用它而不是仅仅说std :: cout。 所以在这里我有这个例子,我必须创建一个新的类名为堆栈与pop()函数(就像在C++已经提供的类)。使用ostream作为函数参数

这里list_node是一个由两个元素组成的结构体:键(它是一个整数)和一个指向下一个整数的interator。 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; 
}; 

,这里是与我的一部分遇到问题:

​​

我不明白他们为什么使用ostream &作为函数参数。难道他们不仅仅把top_node作为参数,而且还使用了.next函数(.next读取下一个list_node),然后他们可以用std :: cout函数打印它。为什么这样做会更好?

+3

首先,'std :: ostream'肯定是**不是**'std :: cout'的另一个名字。前者是基类,其次是未指定类型的对象。其次,目前还不清楚你在问什么。 – SergeyA

+0

该方法是在堆栈内定义的吗? 'top_node'是堆栈类的成员吗?真的不清楚你在问什么;它看起来像有很多遗漏的上下文。 –

+0

你应该提供[mcve] –

回答

0

为什么这样做会更好?

我不确定你的问题,并不确定它是一种更好的方法。

也许是为了灵活性。下面是从我的应用程序库的例子:


当我宣布一个数据属性,作为一个ostream

class T431_t 
{ 
    // ... 
    std::ostream*  m_so; 
    // ... 

我可以平凡使用属性提供的报告“其中,m_so点” 。在这个应用程序中,有几个例子* mso < < ...正在使用。这是主要的例子。

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; 
    // ... 
} 

注意,在类的构造函数(构造函数),对于m_so到std ::法院缺省分配。

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 ::法院和线程2使用m_ssMagic, '主'(线程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”初始化为& std :: cout,并且b)找到了std :: cout的所有用法。其中大部分我简单替换为“* m_so”。然后我c)证实我没有破坏单线程解决方案。很容易,并尝试第一次。

后续工作实现了命令行'双线程'选项。

我认为这个方法将适用于我的下一个桌面,当预算允许时。


,并从OOP的角度来看,这方面的努力工作,因为的std :: ostream的是在这两种性病::法院和std :: stringstream的的类层次结构。因此

"std::cout is-a std::ostream", 

"std::stringstream is-a std::ostream". 

所以m_so可以指向派生类的实例,并提供虚拟方法的ostream接入'要么目的地。