#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++进行面向对象编程,包括类、结构体的定义,函数指针的应用以及组合关系。然而,仍然有一些改进的空间:
-
内存管理:
- 当前代码中为
BWMthree.pwl分配了动态内存,但没有释放它。这会导致内存泄漏。应当在适当的时候(如不再需要该对象时)调用delete来释放。 - 类似的,对于
AodiA6->pwl也应考虑内存管理问题。
- 当前代码中为
-
使用智能指针:
- 为了更安全地管理动态分配的对象,可以考虑使用C++中的智能指针(如
std::unique_ptr或std::shared_ptr),以避免手动管理内存带来的风险。
- 为了更安全地管理动态分配的对象,可以考虑使用C++中的智能指针(如
-
成员函数绑定:
- 使用函数指针虽然灵活,但在C++中可以利用虚函数和多态性实现类似的功能,这样可以使代码更加简洁,并且提高类型安全性。
-
重复代码:
- 对于设置轮胎信息的部分存在重复代码,可以通过创建一个初始化wheel的方法来减少重复。
-
硬编码的打印方法:
- 目前每种车型都有自己特定的打印方法(
bwmThreePrintCarInfo,A6PrintCarInfo),可以考虑将这些逻辑整合到各自的类或子类中,以提高代码的可维护性和扩展性。
- 目前每种车型都有自己特定的打印方法(
-
使用
std::string与printf混用:- 在
bwmThreePrintCarInfo和A6PrintCarInfo函数中混合使用了std::string和printf,建议统一使用C++风格的输出(如std::cout),以保持代码一致性并充分利用C++的优势。
- 在
-
异常处理:
- 增加对可能出现错误情况的处理(例如动态内存分配失败的情况),虽然在这个例子中可能不是特别关键,但在大型项目中是必要的。
-
命名规范:
- 尽量使用一致且具有描述性的命名规则,比如变量名
BWMthree和AodiA6可以改为更具描述性的名称,如bmwThreeSeries和audiA6等。
- 尽量使用一致且具有描述性的命名规则,比如变量名
通过以上几点改进,可以使代码更加健壮、易读、易于维护。此外,还可以进一步探索设计模式的应用,如工厂模式或策略模式,以便更好地组织和扩展你的代码。
以下是对你提供的 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 类并重写方法即可 |
🧠 可进一步拓展的方向:
- 工厂模式:添加一个
CarFactory类,根据参数返回不同类型的Car。 - 策略模式:将“打印行为”抽离为接口,动态更换打印格式。
- 日志系统:将输出转为日志记录功能。
- 序列化/反序列化:支持保存到文件或从文件加载汽车数据。
如果你希望我继续帮你实现这些高级功能(如工厂模式、策略模式等),也可以告诉我!

被折叠的 条评论
为什么被折叠?



