C++ 缩进输出类继承 ofstream

标签 c++ c++11 std ofstream manipulators

所以我想写一个可以像这样使用的缩进输出类:

Debug f;
f.open("test.txt");
f << Debug::IndS << "Start" << std::endl;
f << Debug::Ind << "test" << std::endl;
f << Debug::IndE << "End" << std::endl;

输出:

Start
    test
End

因此 IndS 将打印出当前缩进量和递增缩进量,Ind 将打印出当前缩进量,IndE 将递减缩进量并打印出当前缩进量。我试过这样创建它:

class Debug : public std::ofstream {
    public:
        Debug();
        ~Debug();

    private:
        std::string IndentText;
        int _Indent;

    public:
        void SetIndentText(const char* Text);
        inline void Indent(int Amount);
        inline void SetIndent(int Amount);

        inline std::ofstream& Ind (std::ofstream& ofs);
        inline std::ofstream& IndS(std::ofstream& ofs);
        inline std::ofstream& IndE(std::ofstream& ofs);
};

Debug::Debug () : std::ofstream() {
    IndentText = "    ";
}

Debug::~Debug () {
}

void Debug::SetIndentText (const char* Text) {
    IndentText = Text;
}

void Debug::Indent (int Amount) {
    _Indent += Amount;
}

void Debug::SetIndent(int Amount) {
    _Indent = Amount;
}

std::ofstream& Debug::Ind (std::ofstream& ofs) {
    for (int i = 0;i < _Indent;i++) {
        ofs << IndentText;
    }
    return ofs;
}

std::ofstream& Debug::IndS (std::ofstream& ofs) {
    ofs << Ind;
    _Indent++;
    return ofs;
}

std::ofstream& Debug::IndE (std::ofstream& ofs) {
    _Indent--;
    ofs << Ind;
    return ofs;
}

所以我认为这有几个问题:

  1. 它不编译。 no match for 'operator<<' (operand types are 'std::ofstream {aka std::basic_ofstream<char>}' and '<unresolved overloaded function type>') ofs << Ind; candidates are: 错误呜呜呜

  2. 我没有覆盖所有构造函数。有没有办法做到这一点?我想我只需要重写所有的构造函数来做 IndentText = " ";并委托(delegate)重载的构造函数

有人可以帮我解决这个问题吗?谢谢!

最佳答案

你通常不应该继承std::ostream或者像 std::ofstream 这样的实现.而是将它们包装到另一个类中。

这是我在评论中提到的想法的简短概述

#include <iostream>
#include <fstream>

using namespace std;

class Logger {
public:
    Logger(ostream& os) : os_(os), curIndentLevel_(0) {}
    void increaseLevel() { ++curIndentLevel_; }
    void decreaseLevel() { --curIndentLevel_; }

private:
    template<typename T> friend ostream& operator<<(Logger&, T);

    ostream& os_;
    int curIndentLevel_;
};

template<typename T> 
ostream& operator<<(Logger& log, T op) {
    for(int i = 0; i < log.curIndentLevel_ * 4; ++i) {
        log.os_ << ' ';
    }
    log.os_ << op;
    return log.os_;
}

int main() {
    Logger log(cout);
    log.increaseLevel();
    log << "Hello World!" << endl;
    log.decreaseLevel();
    log << "Hello World!" << endl;
    return 0;
}

输出

    Hello World!
Hello World!

Live Sample


这里有一个小变体,展示了如何使用 operator<<() 简化编码重载:

class Logger {
public:
    Logger(ostream& os) : os_(os), curIndentLevel_(0) {}
    Logger& increaseLevel() { ++curIndentLevel_; return *this; }
    Logger& decreaseLevel() { --curIndentLevel_; return *this; }

    // ... as before ...        
};

int main() {
    Logger log(cout);

    log.increaseLevel() << "Hello World!" << endl;
    log.decreaseLevel() << "Hello World!" << endl;
    return 0;
}

Live Sample

您可以采用相同的方式提供额外的 I/O 操纵器样式的免费功能。

关于C++ 缩进输出类继承 ofstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25216993/

相关文章:

c++ - "not in this scope"cpp函数调用错误

c++ - 尝试使用共享库部署 Qt 应用程序时出错

C++:将像 unique_ptr::get() 这样的参数传递给函数是否安全

C++ 对象实例化数组(我试图找到一个编译时解决方案)

c++ - 重载运算符以合并 vector

C++ 通过引用传递不改变参数

c++ - 检查数组中的所有值

c++ - 检查是否存在全局(/命名空间)函数/对象声明

c++ - 如何在 C++ 中正确填写列表列表

c++插入空 vector 不能使用大括号