You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C++中未知子类类型的Vehicle类文件解析与对象创建问题

嘿,这个场景我刚好在之前的一个车辆管理项目里实现过,咱们一步步来搞定它:

实现思路与代码示例

核心思路是工厂模式+多态解析:用基类的静态方法作为工厂,根据文件开头的类型标识创建对应子类对象,再调用子类各自的解析方法处理不同格式的内容。

步骤1:完善基类Vehicle的定义

首先要给基类加上纯虚的解析接口和虚析构函数,确保子类能正确实现自己的解析逻辑,且内存释放安全:

#include <fstream>
#include <memory>
#include <string>
#include <stdexcept>

class Vehicle {
public:
    // 静态工厂方法:负责创建子类对象并完成解析
    static std::unique_ptr<Vehicle> createAndParse(std::ifstream& in);

    // 纯虚解析方法:子类必须实现各自的格式解析逻辑
    virtual void parse(std::ifstream& in) = 0;

    // 虚析构函数:确保子类析构函数被正确调用
    virtual ~Vehicle() = default;
};

步骤2:实现子类的解析逻辑

每个子类(Car、Truck、Ship)继承Vehicle后,实现自己的parse方法,对应各自的文件格式:

Car子类示例

class Car : public Vehicle {
private:
    int doorCount;
    std::string brand;
public:
    void parse(std::ifstream& in) override {
        // 假设Car的文件格式是:Car [车门数] [品牌]
        if (!(in >> doorCount >> brand)) {
            throw std::runtime_error("Failed to parse Car data");
        }
        // 这里可添加数据验证逻辑,比如车门数不能为负
    }
};

Truck子类示例

class Truck : public Vehicle {
private:
    double loadCapacity; // 载重(吨)
    std::string chassisNumber;
public:
    void parse(std::ifstream& in) override {
        // 假设Truck的文件格式是:Truck [载重] [底盘号]
        if (!(in >> loadCapacity >> chassisNumber)) {
            throw std::runtime_error("Failed to parse Truck data");
        }
    }
};

Ship子类示例

class Ship : public Vehicle {
private:
    int passengerCapacity;
    std::string shipName;
public:
    void parse(std::ifstream& in) override {
        // 假设Ship的文件格式是:Ship [载客量] [船名]
        if (!(in >> passengerCapacity >> shipName)) {
            throw std::runtime_error("Failed to parse Ship data");
        }
    }
};

步骤3:实现基类的静态工厂方法

在这个方法里,先读取文件开头的类型标识,创建对应子类对象,再调用其parse方法完成解析:

std::unique_ptr<Vehicle> Vehicle::createAndParse(std::ifstream& in) {
    if (!in.is_open()) {
        throw std::invalid_argument("File is not open");
    }

    std::string vehicleType;
    // 读取文件开头的类型标识
    if (!(in >> vehicleType)) {
        throw std::runtime_error("Failed to read vehicle type from file");
    }

    std::unique_ptr<Vehicle> vehicle;
    // 根据类型创建对应子类对象
    if (vehicleType == "Car") {
        vehicle = std::make_unique<Car>();
    } else if (vehicleType == "Truck") {
        vehicle = std::make_unique<Truck>();
    } else if (vehicleType == "Ship") {
        vehicle = std::make_unique<Ship>();
    } else {
        throw std::invalid_argument("Unknown vehicle type: " + vehicleType);
    }

    // 调用子类的解析方法处理剩余内容
    vehicle->parse(in);

    return vehicle;
}

使用示例

你可以这样调用这个静态方法:

int main() {
    std::ifstream file("file.vehicle");
    try {
        auto vehicle = Vehicle::createAndParse(file);
        // 此时vehicle已经是对应子类的对象,可后续处理(比如调用其他虚方法)
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

关键注意事项

  • 虚析构函数:基类必须有虚析构,否则当通过基类指针/智能指针销毁子类对象时,会导致未定义行为。
  • 智能指针:用std::unique_ptr代替裸指针,自动管理内存,避免泄漏。
  • 错误处理:添加文件流状态检查和异常抛出,方便定位解析错误。
  • 格式一致性:确保每个子类的parse方法严格对应文件中该类型的格式,比如如果文件里Car的行是Car 4 Tesla,那parse就要按顺序读取整数和字符串。

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

火山引擎 最新活动