You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将文本文件中的游戏分类至对应类并调用多态getMonthlyCost函数?

我来一步步帮你解决这个问题。首先你的现有代码存在不少语法和设计问题,得先修正这些,才能顺利实现从文本文件加载游戏并调用对应方法的功能。接下来我们会搞定文件解析和对应类对象的实例化,最后再给你一些改进建议。

第一步:修复类结构的核心问题

你的原代码有很多影响功能实现的问题,先逐一修正:

  • 重复定义成员变量:子类(比如MMO、Strategy)不需要重新定义Name和Description,基类Game/Console已经有这些成员,应该把基类的成员设为protected,让子类可以直接访问,避免冗余。
  • 构造函数访问权限与初始化错误:基类Game和Console的构造函数默认是私有,子类无法调用;而且子类构造函数的初始化列表写法错误,比如PC():Game(Name,Description)里的Name是未初始化的局部变量,应该通过构造函数参数传入值。
  • 多态接口缺失:要实现多态调用getMonthlyCost,基类必须定义一个虚函数作为接口,最好是纯虚函数,强制子类实现自己的版本。
  • 函数语法错误:getMonthlyCost函数没有返回值,而且表达式没有return语句;构造函数末尾缺少分号。

修正后的基类和子类示例:

#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <string>

using namespace std;

// 抽象基类:Game,所有游戏的父类
class Game {
protected:
    string Name;
    string Category; // 用Category代替Description更贴合业务场景
public:
    Game(string name, string category) : Name(move(name)), Category(move(category)) {}
    // 纯虚函数,强制子类实现月费计算逻辑
    virtual double getMonthlyCost() const = 0;
    virtual ~Game() = default; // 虚析构函数,避免内存泄漏
    string getName() const { return Name; }
    string getCategory() const { return Category; }
};

// PC游戏基类,继承自Game
class PCGame : public Game {
protected:
    double basePrice;
public:
    PCGame(string name, string category, double basePrice) 
        : Game(move(name), move(category)), basePrice(basePrice) {}
};

// MMO子类
class MMO : public PCGame {
private:
    const double monthlyFee = 14.99; // 固定月费
public:
    MMO(string name, double basePrice) 
        : PCGame(move(name), "MMO", basePrice) {}
    
    double getMonthlyCost() const override {
        return monthlyFee; // MMO只收取固定月费
    }
};

// Strategy子类
class Strategy : public PCGame {
private:
    const double monthlyServiceRate = 0.05; // 每月收取基础价的5%作为服务费
public:
    Strategy(string name, double basePrice) 
        : PCGame(move(name), "Strategy", basePrice) {}
    
    double getMonthlyCost() const override {
        return basePrice * monthlyServiceRate; // 计算月服务费
    }
};

// Console游戏基类,继承自Game
class ConsoleGame : public Game {
protected:
    double basePrice;
public:
    ConsoleGame(string name, string category, double basePrice) 
        : Game(move(name), move(category)), basePrice(basePrice) {}
};

// Arcade子类
class Arcade : public ConsoleGame {
public:
    Arcade(string name, double basePrice) 
        : ConsoleGame(move(name), "Arcade", basePrice) {}
    
    double getMonthlyCost() const override {
        return basePrice + (basePrice * 0.10); // 基础价加10%服务费
    }
};

// AR子类
class AR : public ConsoleGame {
private:
    double equipmentCost;
public:
    AR(string name, double basePrice, double equipmentCost) 
        : ConsoleGame(move(name), "AR", basePrice), equipmentCost(equipmentCost) {}
    
    double getMonthlyCost() const override {
        return equipmentCost + basePrice; // 设备费加基础月费
    }
};
第二步:从文本文件加载游戏并实例化对应类

接下来我们需要读取文本文件,每两个条目为一组(游戏名+分类),然后根据分类创建对应的子类对象,用基类智能指针存储,这样就能实现多态调用getMonthlyCost。

假设你的文本文件games.txt内容格式如下(每行一个条目,两两一组):

League Of Legends
MMO
World Of Warcraft
MMO
Civilization
Strategy
Hearthstone
Strategy
Street Fighter
Arcade
PacMan
Arcade
Beat Saber
AR
Superhot
AR

读取并处理的代码:

int main() {
    vector<unique_ptr<Game>> gameList;
    ifstream file("games.txt");
    if (!file.is_open()) {
        cerr << "无法打开游戏文件!" << endl;
        return 1;
    }

    string gameName, category;
    // 每读取两行:第一行是游戏名,第二行是分类
    while (getline(file, gameName) && getline(file, category)) {
        // 根据分类创建对应对象(这里的基础价/设备费是示例值,你可以写到文件里或者从配置读取)
        if (category == "MMO") {
            gameList.emplace_back(make_unique<MMO>(gameName, 0.0));
        } else if (category == "Strategy") {
            gameList.emplace_back(make_unique<Strategy>(gameName, 59.99));
        } else if (category == "Arcade") {
            gameList.emplace_back(make_unique<Arcade>(gameName, 19.99));
        } else if (category == "AR") {
            gameList.emplace_back(make_unique<AR>(gameName, 29.99, 99.99));
        } else {
            cerr << "未知分类:" << category << ",跳过游戏:" << gameName << endl;
        }
    }

    // 遍历所有游戏,调用getMonthlyCost计算并输出月费
    cout << "各游戏月费用计算结果:" << endl;
    for (const auto& game : gameList) {
        cout << "游戏:" << game->getName() 
             << ",分类:" << game->getCategory() 
             << ",月费用:$" << game->getMonthlyCost() << endl;
    }

    return 0;
}
关键改进与批评建议
  1. 类设计冗余:原代码重复定义Name和Description属于典型的冗余设计,基类成员设为protected即可让子类访问,减少维护成本和内存浪费。
  2. 多态实现错误:原代码没有在基类定义虚函数,导致无法实现多态调用;子类的virtual用法也有误(基类声明虚函数后,子类用override标记即可)。
  3. 语法漏洞:原代码的构造函数缺少分号、getMonthlyCost无返回值,这些都是编译级错误,必须优先修正。
  4. 扩展性优化建议:
    • 可以把游戏的基础价格、设备费等信息也写入文本文件,避免代码硬编码,提升灵活性。
    • 使用unique_ptr代替原始指针,自动管理内存,避免内存泄漏。
    • 可以封装工厂模式,把创建游戏对象的逻辑单独抽离,简化main函数的复杂度。
    • 把getMonthlyCost设为const成员函数,因为它不会修改对象状态,符合代码规范。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 11:12:33