【发布时间】:2018-11-30 14:40:43
【问题描述】:
我有一个基类 Auto_Part 和几个派生类,如 class Battery、class Engine、class Frame 等。我还有一个派生的孙子 class Car,它继承了所有派生部分类。
我的目标:我有一个 Inventory class 和一个库存对象 map<Auto_Part*, int> 。第一个值是要存储的 Auto_Part 参考,第二个值是库存中有多少可用。 用户应该能够使用库存中可用的零件创建汽车对象。我想遍历此地图并使用适当的访问器方法来获取创建我的汽车对象所需的数据。 p>
这是有问题的功能。我正在尝试使用 MVC 模型,因此它是一个控制器功能。
void Controller::add_car_from_parts(){
//All variables used in all of the parts
std::string type, frame_type, category, color, bolt_pattern, tire_type, speed_rating,load_range, w_frame_type;
std::string name, fuel_type, grip_type, horn_type, display_color, seat_material, seat_warmers, door_material, butterfly_doors;
int part_number, cranking_amps, cold_cranking_amps, voltage,diameter,width,ratio, w_diameter,w_width, num_doors,
length,reserve_capacity_minutes,num_cylinders, steering_wheel_diameter, num_seats, display_length;
double price;
int quantity;
Dialogs::message("You will be shown the parts available in the inventory. Please write down the part number of the part you will add to you vehicle.", "PART NUMBER");
view.view_all_inventory();
part_number = view.pn_prompt();
//quantity = view.quantity_prompt();
for(auto x: inventory.get_inventory()){ //inventory is a map<Auto_Part*,int>
if (x.first->get_part_number() == part_number){ // If part is in the inventory
if (x.first->get_type() == "Battery"){// and if the part is a battery, auto_part function available in all auto_part classes including class Auto_Part
name = x.first->get_name(); // auto_part function, available in all auto_part classes including class Auto_Part
price = x.first->get_price(); // auto_part function, available in all auto_part classes including class Auto_Part
cranking_amps = x.first->get_cranking_amps(); // battery function only
cold_cranking_amps = x.first->get_cold_cranking_amps(); // battery function only
voltage = x.first->get_voltage(); // battery function only
reserve_capacity_minutes = x.first->get_reserve_capacity_minutes(); //battery function only
inventory.remove_parts(x.first,1); // removes part from inventory, second value is quantity removed
}
}
}
}
所以x.first->get_part_number()、x.first->get_type()、x.first->get_name() 和 x.first->get_price() 工作正常,因为它们在 Auto_Part 类以及所有派生类中,因此在迭代时指向适当的 get 函数. 第一个错误在cranking_amps = x.first->get_cranking_amps() 行,我的编译器说“类 Auto_Part 没有 get_cranking_amps() 函数,只有电池函数。”
我想既然地图是由Auto_Part* 而不仅仅是Auto_Part 对象组成的,它会引用适当的类。正如 x 会随着它在映射中迭代到 Battery 对象或 Engine 对象而改变,这取决于它是什么,因此我可以使用它的独特功能。 如何在遍历这个基类引用列表时调用派生类函数?当然,我不需要在基类中创建每个派生类函数,对吧?这似乎会破坏具有独特功能的派生类的目的。
感谢您的宝贵时间。
【问题讨论】:
-
除非我的search-fu很弱,否则问题不包含
virtual这个词。您将要对get_cranking_amps()等使用虚拟函数。然后您可以调用base_class_pointer->get_cranking_amps()并知道正在调用正确的函数。如果你用电池调用它,它会得到正确的号码。如果你在其他东西上调用它,它可以返回0或-1或其他对你有意义的值。 -
我强烈建议不要让
Car继承自Battery、Engine等等。它可能有这些类型的成员数据,但继承在这里无用。 -
一个糟糕的解决方案是将 dynamic_cast 转换为您认为的类型 - 在不是的情况下处理这种情况。一个更好的解决方案可能是有一个 getproperties,它会返回一个属性/值对的映射,供调用者使用,调用者可以选择他想要的东西。 that 的更好版本将是访问者模式。
-
@Caleth - 绝对正确 - 但我不明白你是如何从给出的代码中得出这个结论的。来自“auto_part”的引擎和电池似乎没问题。
-
@davidbak 我不是在谈论
AutoPart作为基础。即便如此,我还是很想将库存设为vector<variant<Battery, Engine, Frame, ...>>,而不是vector<auto_part_ptr>
标签: c++