使用私有枚举成员重载输出(<<<)运算符

时间:2016-02-23 08:27:31

标签: c++ algorithm multimap

我很难尝试重载我的<<此类的输出运算符。该班级有私人会员 - enum classstring。我编写的代码编译并运行,但<<运算符仅为枚举类重载。 根据我的理解和阅读,我需要做出类似的事情:

  朋友ostream&运算符<<(ostream& os,CDirectory const& dir)

但我似乎未能实现它,此时我真的没有想法。我想为整个class CDirectory重载运算符,而不仅仅是enum class Filetype,即其中一个成员。这甚至可以吗?

class CDirectory {
    string m_strDirectory;
    enum class Filetype {
        Archive, Hidden, ReadOnly, System, FileNotSupported
    };
    multimap <CFile, Filetype> m_DirectoryMap;
public:
    /* overloading operator<< for the enum class Filetype */
    friend ostream& operator<<(ostream& os, Filetype const type)
    {
        switch (type)
        {
        case Filetype::Archive:
            os << "archive";
            break;
        case Filetype::Hidden:
            os << "hidden";
            break;
        case Filetype::ReadOnly:
            os << "read-only";
            break;
        case Filetype::System:
            os << "system";
            break;
        case Filetype::FileNotSupported:
            os << "not-supported";
            break;
        }
        return os;
    }
    /* explicit constructor - reads data from a file and inserts pairs
      of types pair <CFile, enum Filetype> in a multimap */
    CDirectory (const string& n) {
        fp.open (n, ios::in);
        string dirName, fileName,  fType;
        int fileSize;
        Filetype filetype;
        fp >> dirName;
        m_strDirectory = dirName;
        while (fp >> fileName >> fileSize >> fType) {
            CFile obj (fileName, fileSize);
            if (fType == "Archive")
                filetype = Filetype::Archive;
            else if (fType == "Hidden")
                filetype = Filetype::Hidden;
            else if (fType == "ReadOnly")
                filetype = Filetype::ReadOnly;
            else if (fType == "System")
                filetype = Filetype::System;
            else
                filetype = Filetype::FileNotSupported;
            m_DirectoryMap.insert(pair<CFile, Filetype>(CFile(obj.getFileName(), obj.getFileSize()), Filetype(filetype)));
        }
        auto p = m_DirectoryMap.begin();
        cout << m_strDirectory << endl;
        while ( p != m_DirectoryMap.end()) {
            cout << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p->second << endl;
            ++p;
        }
    }
    void printMap () {
         auto p = m_DirectoryMap.begin();
         cout << m_strDirectory << endl;
         while ( p != m_DirectoryMap.end()) {
                cout << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p->second << endl;
                ++p;
        }
    }
};

更新

我尝试了以下代码,用于实现重载运算符&lt;&lt;对于我的整个班级,但它会在这些行上产生错误 - error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'|(其中1个在我的构造函数中,1个在我的printMap函数中) - cout << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p-&gt; second&lt;&lt; ENDL; 我猜它与p->second部分有关,但我不知道到底发生了什么。有什么想法吗?

更新:是的,问题是当我尝试用p->second打印枚举时。如果我删除那部分,它就会编译..

std::ostream& operator<<(std::ostream &os, const CDirectory &dir)
    {
        const Filetype& type;
        switch (type)
        {
        case Filetype::Archive:
            os << "archive";
            break;
        case Filetype::Hidden:
            os << "hidden";
            break;
        case Filetype::ReadOnly:
            os << "read-only";
            break;
        case Filetype::System:
            os << "system";
            break;
        case Filetype::FileNotSupported:
            os << "not-supported";
            break;
        }
        os << dir.m_strDirectory << "\n";
        for(auto &p : dir.m_DirectoryMap) {
           os << p.first.getFileName() << '\t' << p.first.getFileSize() << '\t' << p.second << '\n';
        }
        return os;
    }

3 个答案:

答案 0 :(得分:2)

我认为最终你希望能够做到这样的事情:

CDirectory dir("input_file");
std::cout << dir;

这应该一次输出所有内容(基本上是CDirectory::printMap()当前打印的所有内容,对吧?

为此,您需要为operator<<类重载CDirectory作为非成员函数:

std::ostream& operator<<(std::ostream &os, const CDirectory &dir)
{
    os << dir.m_strDirectory << "\n";
    for(auto &p : dir.m_DirectoryMap) {
        std::cout << p.first.getFileName() << '\t' << p.first.getFileSize() << '\t' << p.second << '\n';
    }

    return os;
}

然后让这个功能成为你班级的朋友:

friend std::ostream& operator<<(std::ostream &os, const CDirectory &dir);

可以访问该班级的私​​人会员。

或者,因为你的班级已经有了打印功能,你可以转发到那个,这样你就不需要让operator<<成为朋友(有些人对朋友的功能不满)。为此,您必须稍微更改printMap()功能:

void printMap (std::ostream &os) const
{
     auto p = m_DirectoryMap.begin();
     os << m_strDirectory << endl;
     while ( p != m_DirectoryMap.end()) {
            os << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p->second << endl;
            ++p;
    }
}

std::ostream& operator<<(std::ostream &os, const CDirectory &dir)
{
    dir.printMap();
    return os;
}

一旦你有了这个操作符,用你的main()函数写的两个变体中的任何一个,你可以写:

CDirectory dir("input_file");
std::cout << dir;

有关您已为Filetype重载的操作员的两个注释。它是唯一需要为您的类重载可以流式处理的其他运算符(operator<<已经为std::string和整数类型重载,因此您无需执行此操作即可写字符串和数字)。还要记住,即使你在类中写了它,它实际上不是一个成员函数,也不能成为一个成员函数(为什么?)。您可以在那里定义它,因为您声明它friend,但定义友元函数的常用方法是:

class A {
    ...
    friend void f();
    ...
};

void f() {
    ...
}

答案 1 :(得分:1)

我的印象是您在类的数据成员和嵌套类型(成员类型)之间感到困惑。操作员(将被定义)用于类型,而不是数据成员。

您必须为要使用它的每个类/类型重载ostream& operator<<(ostream& os, Filetype const type) (用于流输出),并且尚未定义它。从你的代码中,我认为你只需要重载

{{1}}
你做了什么。所以目前还不清楚你的问题究竟是什么以及症状是什么。

答案 2 :(得分:0)

在我看来,你拥有所需的一切,你只需要把它放在一起。

printMap()功能已经打印了class CDirectory中的所有内容。它将所有内容打印到cout。所以你可以做以下事情,它应该可以工作。

friend ostream& operator<<(ostream& os, const CDirectory& dir)
{
    dir.printMap();
}

但是这段代码编写得不好,因为opeartor<<更为通用,而不仅仅是cout。为了使它更好,您可以重写printMap()函数以引用要输出的ostream

void printMap (ostream& os) 
{
     os << m_strDirectory << endl;

     auto p = m_DirectoryMap.begin();
     while ( p != m_DirectoryMap.end()) 
     {
            os << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p->second << endl;
            ++p;
     }
}

void printMap () { printMap(std::cout); }

现在运营商看起来像这样:

friend ostream& operator<<(ostream& os, const CDirectory& dir)
{
    dir.printMap(os);
}

我希望这能更好地解释发生了什么。