使用 ifstream 构建 class Poet,然后使用相同的 ifstream 构建其成员 class Verse
Constructing a class Poet with ifstream and then constructing it's member class Verse with same ifstream
想象一个名为 Poet 的 class 成员 FirstName、LastName 和 class 名为 Verse 的成员作为 Poet 的成员。是否可以用ifstream构造Poet,然后用ifstream初始化FirstName和LastName,然后用相同的ifstream构造成员Verse?我的意思是,如何在初始化一些成员后将 ifstream 从一个 class 正确传递给它的成员 class?谢谢
第 1 步:将运算符 >> 添加到 Verse
这是一个完全琐碎的 >>
基于 What are the basic rules and idioms for operator overloading?
因为我不知道 Verse
里面应该放什么,所以我坚持使用一行的字面定义。
friend std::istream& operator>>(std::istream& in, Verse & obj)
{
std::getline(in, obj.line);
return in;
}
这使您可以从任何流(而不仅仅是 fstream
)读取到 Verse
。在有意义的地方,从最高抽象级别开始工作以获得更通用的解决方案。
第 2 步:在构造函数中使用 Verse
的 >>
。
我正在抛硬币,看看在构造函数中这样做是否是一件好事。与任何其他函数一样,构造函数应该完成一项工作。构造函数的工作是初始化一个对象。从文件中读取可能经常会超出一个作业规则。另一个原因是构造函数只有(或应该)有两种方法:使用初始化对象或抛出异常,而异常是昂贵的。 IO 有很大的出错空间,因此您可能会发现自己抛出异常的频率比您希望的要高。
Poet(std::istream & in)
{
in >> FirstName >> LastName >> Verse;
if (!in)
{
throw std::runtime_error("Aaaaaaaarrrggghhhh!");
}
}
再次注意,我已将输入流从文件流扩展到所有 istream
s 以概括函数。
读取失败也不例外。你得到一个对象,或者你没有。
最后说明(Baring 编辑)这个解决方案在面对像 "Johann von Goethe" 这样的诗人名字时非常失败,因为它只接受一个单词的名字。
我找到了另一种方法。 Poet.h:
private:
std::string FirstName;
std::string LastName;
int BirthYear;
bool IsAlive;
int DeathYear;
Verse FirstVerse;
class Poet.cpp 中的诗人重载构造函数:
Poet::Poet(std::ifstream & in):DeathYear(0)
{
std::getline(in, FirstName);
std::getline(in, LastName);
in >> BirthYear;
in >> IsAlive;
setDeathYearIfNotAlive(in);
//in >> FirstVerse;
FirstVerse.~Verse();
new(&FirstVerse) Verse(in);
}
请注意,"in" 没有重载友元运算符 >>,它是基本的 std::ifstream in
想象一个名为 Poet 的 class 成员 FirstName、LastName 和 class 名为 Verse 的成员作为 Poet 的成员。是否可以用ifstream构造Poet,然后用ifstream初始化FirstName和LastName,然后用相同的ifstream构造成员Verse?我的意思是,如何在初始化一些成员后将 ifstream 从一个 class 正确传递给它的成员 class?谢谢
第 1 步:将运算符 >> 添加到 Verse
这是一个完全琐碎的 >>
基于 What are the basic rules and idioms for operator overloading?
因为我不知道 Verse
里面应该放什么,所以我坚持使用一行的字面定义。
friend std::istream& operator>>(std::istream& in, Verse & obj)
{
std::getline(in, obj.line);
return in;
}
这使您可以从任何流(而不仅仅是 fstream
)读取到 Verse
。在有意义的地方,从最高抽象级别开始工作以获得更通用的解决方案。
第 2 步:在构造函数中使用 Verse
的 >>
。
我正在抛硬币,看看在构造函数中这样做是否是一件好事。与任何其他函数一样,构造函数应该完成一项工作。构造函数的工作是初始化一个对象。从文件中读取可能经常会超出一个作业规则。另一个原因是构造函数只有(或应该)有两种方法:使用初始化对象或抛出异常,而异常是昂贵的。 IO 有很大的出错空间,因此您可能会发现自己抛出异常的频率比您希望的要高。
Poet(std::istream & in)
{
in >> FirstName >> LastName >> Verse;
if (!in)
{
throw std::runtime_error("Aaaaaaaarrrggghhhh!");
}
}
再次注意,我已将输入流从文件流扩展到所有 istream
s 以概括函数。
读取失败也不例外。你得到一个对象,或者你没有。
最后说明(Baring 编辑)这个解决方案在面对像 "Johann von Goethe" 这样的诗人名字时非常失败,因为它只接受一个单词的名字。
我找到了另一种方法。 Poet.h:
private:
std::string FirstName;
std::string LastName;
int BirthYear;
bool IsAlive;
int DeathYear;
Verse FirstVerse;
class Poet.cpp 中的诗人重载构造函数:
Poet::Poet(std::ifstream & in):DeathYear(0)
{
std::getline(in, FirstName);
std::getline(in, LastName);
in >> BirthYear;
in >> IsAlive;
setDeathYearIfNotAlive(in);
//in >> FirstVerse;
FirstVerse.~Verse();
new(&FirstVerse) Verse(in);
}
请注意,"in" 没有重载友元运算符 >>,它是基本的 std::ifstream in