我很难尝试重载我的<<此类的输出运算符。该班级有私人会员 - enum class
和string
。我编写的代码编译并运行,但<<运算符仅为枚举类重载。
根据我的理解和阅读,我需要做出类似的事情:
朋友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;
}
答案 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);
}
我希望这能更好地解释发生了什么。