首页 > 解决方案 > ostream:在 cout 或文件上输出的类

问题描述

我需要编写一个输出到std::cout或某个文件的程序。我正在阅读这篇文章以了解如何做。但是,我想将 ostream 的管理与main. 所以我想写一个类,但我对设计有点困惑。我想到了两个解决方案

  1. (公开)子类 ostream:这样我就有了 ostream 的所有方法。但是这里的主要问题是创建者:

    class sw_ostream : public ostream {
       sw_ostream (cost char* filename) : ostream ( \\? ) {
       \\ ...
       }
    \\...
    }
    

ostream因为我应该根据 进行初始化filename,显然是不可能的。

  1. 创建一个以 osteram 作为成员并重载的类operator<<

我确信这个问题还有其他更优雅的解决方案。你会建议哪种设计?

标签: c++ostream

解决方案


我会尝试将流创建与流使用分开。std::ostream 已经是多态的,所以只要您将引用或指针传递给使用流的函数,一切都很好。

对于创建,我会在堆中创建流,正如您链接到的帖子所建议的那样。但是,进行显式内存管理(原始新/删除)是危险的,所以我会使用智能指针,例如 std::unique_ptr:

#include <fstream>
#include <memory>

struct ConditionalDeleter
{
    bool must_delete;
    void operator()(std::ostream* os) const { if (must_delete) delete os; }
};

using OstreamPtr = std::unique_ptr<std::ostream, ConditionalDeleter>;

OstreamPtr create_stream(bool to_file)
{
    if (to_file)
        return OstreamPtr { new std::ofstream {"myfile.txt"}, ConditionalDeleter {true} };
    else
        return OstreamPtr { &std::cout, ConditionalDeleter {false} };
}

void use_stream(std::ostream& os)
{
    os << "Hello world!" << std::endl;
}

int main()
{
    auto streamptr = create_stream(false);
    use_stream(*streamptr);
}

我使用了带有 std::unique_ptr 的自定义删除器。这样做的原因是:如果我们正在使用文件,我希望删除流;但是 std::cout 是一个全局对象,我们不能删除它。这里的协议是当你的 OstreamPtr 被破坏时, ConditionalDeleter::operator() 将被调用。*streamptr 返回一个对 std::ostream 的引用,您可以随意使用它。

请注意,您需要 C++11 支持才能使用此解决方案。


推荐阅读