编程练习C++类使用

#include <stdio.h>
#include <stdlib.h>
#include<string>
#include<iostream>
using namespace std;

// 定义一个结构体Car,模拟汽车类
struct Car{
    string color; // 颜色
    string brand; // 品牌
    string type; // 车型
    int year; // 年限

    // 函数指针,用于动态绑定打印车辆信息的方法
    void (*printCarInfo)(string color,string brand,string type, int year);
    // 函数指针,用于动态绑定车运行的方法
    void (*carRun)(string type);
    // 函数指针,用于动态绑定车停止的方法
    void (*carStop)(string type);
};

// 定义轮胎类
class wheel{
public:
    string brand; // 轮胎品牌
    int year; // 轮胎年限
    void wheelPrintInfo(); // 打印轮胎信息的方法
};
void wheel::wheelPrintInfo(){
    cout << "我的轮胎品牌是" << brand <<endl;
    cout << "我的轮胎年限是" << year <<endl;
}

// 定义包含组合关系的汽车类(包含了一个wheel对象)
class car{
public:
    string color; // 颜色
    string brand; // 品牌
    string type; // 车型
    int year; // 年限

    wheel wl; // 组合关系:汽车拥有一个wheel对象
    wheel *pwl; // 指向wheel对象的指针

    // 函数指针,用于动态绑定打印车辆信息的方法
    void (*printCarInfo)(string color, string brand, string type, int year);
    // 函数指针,用于动态绑定车运行的方法
    void (*carRun)(string type);
    // 函数指针,用于动态绑定车停止的方法
    void (*carStop)(string type);

    // 成员函数,用于打印汽车信息
    void realPrintCarInfo();
};
void car::realPrintCarInfo(){
    cout << "成员函数打印" << endl;
    string str = "车的品牌是:" + brand
            + ",型号是: " + type
            + ",颜色是:" + color
            + ",上市年限是:" + std::to_string(year);
    cout << str << endl;
}

// 为宝马3系定义的打印车辆信息的函数
void bwmThreePrintCarInfo(string color,string brand,string type, int year)
{
    printf("车的品牌是:%s, 型号是: %s, 颜色是:%s,上市年限是%d\n",brand.c_str(), type.c_str(), color.c_str(), year);
}
// 为奥迪A6定义的打印车辆信息的函数
void A6PrintCarInfo(string color,string brand,string type, int year)
{
    printf("车的品牌是:%s,型号是: %s, 颜色是:%s, 上市年限是%d\n",brand.c_str(), type.c_str(), color.c_str(), year);
}

int main()
{
    // 创建宝马3系汽车实例,并设置属性值
    car BWMthree;
    BWMthree.color = "白色";
    BWMthree.brand = "宝马";
    BWMthree.type = "3系";
    BWMthree.year = 2023;

    // 动态分配内存给BWMthree的轮胎指针,并设置轮胎属性
    BWMthree.pwl = new wheel();
    BWMthree.pwl->brand = "米其林";
    BWMthree.pwl->year = 2023;

    // 绑定宝马3系打印信息的函数
    BWMthree.printCarInfo = bwmThreePrintCarInfo;
    // 调用打印信息函数
    BWMthree.printCarInfo(BWMthree.color, BWMthree.brand, BWMthree.type, BWMthree.year);

    // 创建奥迪A6汽车实例,并设置属性值
    car *AodiA6 = new car();
    AodiA6->color = "黑色";
    AodiA6->brand = "奥迪";
    AodiA6->type = "A6";
    AodiA6->year = 2008;

    // 动态分配内存给AodiA6的轮胎指针,并设置轮胎属性
    AodiA6->pwl = new wheel();
    AodiA6->pwl->brand = "马牌";
    AodiA6->pwl->year = 2023;

    // 直接设置AodiA6的嵌入wheel对象的属性
    AodiA6->wl.brand = "马牌";
    AodiA6->wl.year = 2023;

    // 绑定奥迪A6打印信息的函数,并调用
    AodiA6->printCarInfo = A6PrintCarInfo;
    AodiA6->printCarInfo(AodiA6->color,AodiA6->brand,AodiA6->type,AodiA6->year);

    // 使用成员函数打印奥迪A6的信息
    AodiA6->realPrintCarInfo();

    // 打印奥迪A6的轮胎信息
    AodiA6->pwl->wheelPrintInfo();

    // 释放动态分配的内存
    delete AodiA6;

    return 0;
}

代码改进后

这段代码已经相当全面地展示了如何使用C++进行面向对象编程,包括类、结构体的定义,函数指针的应用以及组合关系。然而,仍然有一些改进的空间:

  1. 内存管理

    • 当前代码中为BWMthree.pwl分配了动态内存,但没有释放它。这会导致内存泄漏。应当在适当的时候(如不再需要该对象时)调用delete来释放。
    • 类似的,对于AodiA6->pwl也应考虑内存管理问题。
  2. 使用智能指针

    • 为了更安全地管理动态分配的对象,可以考虑使用C++中的智能指针(如std::unique_ptrstd::shared_ptr),以避免手动管理内存带来的风险。
  3. 成员函数绑定

    • 使用函数指针虽然灵活,但在C++中可以利用虚函数和多态性实现类似的功能,这样可以使代码更加简洁,并且提高类型安全性。
  4. 重复代码

    • 对于设置轮胎信息的部分存在重复代码,可以通过创建一个初始化wheel的方法来减少重复。
  5. 硬编码的打印方法

    • 目前每种车型都有自己特定的打印方法(bwmThreePrintCarInfoA6PrintCarInfo),可以考虑将这些逻辑整合到各自的类或子类中,以提高代码的可维护性和扩展性。
  6. 使用std::stringprintf混用

    • bwmThreePrintCarInfoA6PrintCarInfo函数中混合使用了std::stringprintf,建议统一使用C++风格的输出(如std::cout),以保持代码一致性并充分利用C++的优势。
  7. 异常处理

    • 增加对可能出现错误情况的处理(例如动态内存分配失败的情况),虽然在这个例子中可能不是特别关键,但在大型项目中是必要的。
  8. 命名规范

    • 尽量使用一致且具有描述性的命名规则,比如变量名BWMthreeAodiA6可以改为更具描述性的名称,如bmwThreeSeriesaudiA6等。

通过以上几点改进,可以使代码更加健壮、易读、易于维护。此外,还可以进一步探索设计模式的应用,如工厂模式或策略模式,以便更好地组织和扩展你的代码。

以下是对你提供的 C++ 代码的 全面改进版本,包括:

  • 使用面向对象设计(继承 + 多态)
  • 使用智能指针管理资源
  • 去除函数指针方式,改用虚函数多态
  • 统一使用 std::cout 输出风格
  • 封装轮胎(wheel)初始化逻辑
  • 更清晰、可扩展的设计

✅ 改进后的代码如下: 

#include <iostream>
#include <memory>
#include <string>

using namespace std;

// 轮胎类
class Wheel {
public:
    string brand;
    int year;

    Wheel(string brand = "未知", int year = 0)
        : brand(brand), year(year) {}

    void printInfo() const {
        cout << "轮胎品牌: " << brand << ", 年限: " << year << "年" << endl;
    }
};

// 汽车基类(抽象类)
class Car {
protected:
    string color;
    string brand;
    string type;
    int year;
    Wheel wheel; // 组合:每个汽车包含一个轮胎

public:
    Car(string color, string brand, string type, int year, Wheel wheel)
        : color(color), brand(brand), type(type), year(year), wheel(wheel) {}

    virtual ~Car() = default;

    // 虚函数:打印车辆信息
    virtual void printCarInfo() const {
        cout << "品牌: " << brand
             << ", 型号: " << type
             << ", 颜色: " << color
             << ", 上市年限: " << year << "年"
             << endl;
    }

    // 虚函数:车运行
    virtual void carRun() const {
        cout << brand << " " << type << " 正在行驶..." << endl;
    }

    // 虚函数:车停止
    virtual void carStop() const {
        cout << brand << " " << type << " 已经停下。" << endl;
    }

    // 打印轮胎信息
    void printWheelInfo() const {
        wheel.printInfo();
    }
};

// 宝马3系子类
class BMWThree : public Car {
public:
    BMWThree(string color, int year, Wheel wheel)
        : Car(color, "宝马", "3系", year, wheel) {}

    void printCarInfo() const override {
        cout << "[宝马3系] 品牌: 宝马, 型号: 3系, 颜色: " << color
             << ", 上市年限: " << year << "年" << endl;
    }
};

// 奥迪A6子类
class AudiA6 : public Car {
public:
    AudiA6(string color, int year, Wheel wheel)
        : Car(color, "奥迪", "A6", year, wheel) {}

    void printCarInfo() const override {
        cout << "[奥迪A6] 品牌: 奥迪, 型号: A6, 颜色: " << color
             << ", 上市年限: " << year << "年" << endl;
    }
};

int main() {
    // 创建轮胎对象
    Wheel bwmWheel("米其林", 2023);
    Wheel audiWheel("马牌", 2023);

    // 使用智能指针创建汽车对象
    unique_ptr<Car> bmwCar = make_unique<BMWThree>("白色", 2023, bwmWheel);
    unique_ptr<Car> audiCar = make_unique<AudiA6>("黑色", 2008, audiWheel);

    // 宝马操作
    bmwCar->printCarInfo();
    bmwCar->carRun();
    bmwCar->carStop();
    bmwCar->printWheelInfo();
    cout << "-----------------------------" << endl;

    // 奥迪操作
    audiCar->printCarInfo();
    audiCar->carRun();
    audiCar->carStop();
    audiCar->printWheelInfo();

    return 0;
}

📌 改进说明总结:

改进点说明
封装性更好使用继承和多态,不同车型通过子类实现各自的行为
安全性更高使用 unique_ptr 管理内存,避免内存泄漏
更符合C++风格使用虚函数代替函数指针,提高类型安全性和可读性
输出统一全部使用 std::cout,避免混用 C 和 C++ 的 I/O 函数
可扩展性强新增车型只需继承 Car 类并重写方法即可

🧠 可进一步拓展的方向:

  1. 工厂模式:添加一个 CarFactory 类,根据参数返回不同类型的 Car
  2. 策略模式:将“打印行为”抽离为接口,动态更换打印格式。
  3. 日志系统:将输出转为日志记录功能。
  4. 序列化/反序列化:支持保存到文件或从文件加载汽车数据。

如果你希望我继续帮你实现这些高级功能(如工厂模式、策略模式等),也可以告诉我!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小范好好学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值