为不同的成员变量在相同 class 中重载运算符 << 两次

Overloading operator<< twice in same class for different member variables

抱歉,如果之前有人问过这个问题,但我正在努力重载 << 运算符以将不同的数据流式传输到多个文件中。

我有一个Playerclass,它具有以下属性:

char* name;
char* password;
int hScore;
int totalGames;
int totalScore;
int avgScore;

我想重载 << 运算符两次:一次是将 namepasswordhScore 流式传输到 "Players.txt" 文件,一次是第二个重载将 totalGamestotalScoreavgScore 流式传输到不同的 .txt 文件,该文件基于每个玩家的名字,例如"Player1.txt".

这是我的运算符在 Player class 中的样子:

friend ostream& operator<< (std::ostream& os, Player& player)
{
    os << player.name << "\n" << player.encryptPassword((player.password), 3) << "\n" << player.hScore << "\n";
    return os;
}

这就是我调用它的地方,来自 PlayerLibrary class,其中包含 Players:

的向量
ofstream out("Yahtzee.txt");
if (out.is_open())
{
    for_each(playerList.begin(), playerList.end(), [&out](Player* player) {out << (*player);});
}
else
{
    cout << "THERE WAS AN ERROR WRITING TO FILE\n";
}

基本上,我想将其他变量流式传输到另一个以玩家姓名命名的文件中,并包含他们玩过的每场比赛的记分卡。到目前为止它看起来像:

for (auto it = playerList.begin(); it != playerList.end(); ++it)
{
    auto position = it - playerList.begin();
    string filename(playerList[position]->getName());
    filename = filename + ".txt";
    ofstream out2(filename);

    for (int i = 0; i < playerList[position]->getNumberOfScorecards(); i++)
    {
        out2 << *playerList[position]->getScorecard(i);
    }
}

这只会流式传输记分卡,而不是 totalGamestotalScoreavgScore,就像我希望的那样。

我试过将这些变量移到记分卡中 class,但我觉得将它们放在原处更有意义。

我知道如果两个重载具有相同的参数,我就不能重载 operator<< 两次,还有其他方法吗?无论如何,在重载函数中是否有可能使用输出流并检查 .txt 文件或其他东西的名称。

希望这个问题有道理。

与其为 Player 本身定义一个 operator<<,不如创建一些引用 Player 并拥有自己的 operator<< 的实用程序类型,让它们决定要流式传输 Player 的哪些部分,例如:

class Player
{
private:
    std::string name;
    std::string password;
    int hScore;
    int totalGames;
    int totalScore;
    int avgScore;
    ...

public:
    ...

    std::string getName{} const { return name; }
    ...

    std::string EncryptPassword(int arg) const { return ...; }

    int getNumberOfScorecards() const { return ...; }
    Scorecard* getScorecard(int index) const { return ...; }

    class Info
    {
        const Player &m_player;

        void print(std::ostream &os) const {
            os << m_player.name << "\n" << m_player.encryptPassword(3) << "\n" << m_player.hScore << "\n";
        }

    public:
        Info(const Player &player) : m_player(player) {}

        friend std::ostream& operator<<(std::ostream &os, const Info &info)
        {
            info.print(os);
            return os;
        }
    };
    friend class Info;

    struct Stats
    {
        const Player &m_player;

        void print(std::ostream &os) const
        {
            os << m_player.totalGames << "\n" << m_player.totalScore << "\n" << m_player.avgScore << "\n";
        }

    public:
        Stats(const Player &player) : m_player(player) {}

        friend std::ostream& operator<<(std::ostream &os, const Stats &stats)
        {
            stats.print(os);
            return os;
        }
    };
    friend class Stats;
};

然后你可以像这样使用它们:

ofstream out("Yahtzee.txt");
if (out.is_open())
{
    for(auto *player : playerList)
        out << Player::Info(*player);
}
else
{
    cout << "THERE WAS AN ERROR WRITING TO FILE\n";
}
for (auto *player : playerList)
{
    ofstream out2(player->getName() + ".txt");
    out2 << Player::Stats(*player);

    for (int i = 0; i < player->getNumberOfScorecards(); ++i)
    {
        out2 << *player->getScorecard(i);
    }
}

Online Demo