我有一个关于面向对象设计的问题。
假设我们有一个可以包含 Vehicle 对象的 Garage 类。这些交通工具可以是汽车或船只。 Boat
和 Car
都扩展了 Vehicle
。
class Garage {
Vehicle & v_;
public Garage(Vehicle & v) : v_(v) {}
public Vehicle getVehicle() { return v_; }
}
但是,我希望车库根据其包含的车辆而有很大不同。所以我考虑创建两个子类,分别是 BoatGarage
和 CarGarage
,它们都扩展了 Garage。
例子:
class BoatGarage : public Garage {
Boat & b_;
public BoatGarage(Boat & b) : Garage(b), b_(b) {}
}
我有几个问题。
通过在构造函数中使用引用作为参数,我可以确保我不会创建另一艘船的拷贝,对吗?如果构造函数是
BoatGarage(Boat b) : Garage(b), b_(b)
,我会创建 2 个船拷贝吗?一个用于 BoatGarage,一个用于 Garage?为同一车辆创建 2 个引用是否有意义?就像在这种情况下,我有一个 Vehicle 引用和一个 Boat 引用同一条船。这是多余的吗?
编辑:澄清一下:我面临的最初问题是我只想要一种非常通用的方式来处理车库和车辆。我只是在尝试一些东西来用 C++ 练习 OOP。我想我希望 Vehicles 基类能够在我想要的时候添加车辆。我创建了一个 Garage 基类,因为也许我想添加一些函数,如“paint boat”或“fix_tire”,以便在知道其类型的情况下对车辆进行修改
最佳答案
- 是的,你在这里写的是正确的。
- 实际上,这是一个糟糕的设计。在一个类中对同一个对象有两个引用意味着通过一个引用访问该对象的代码可能会突然发现该对象已经通过另一个引用发生了变化;它增加了歧义和混淆的可能性,并且随着您的程序变得越来越大,这种歧义可能会引起任何错误。
类层次应该只包含一个对对象的引用。为避免切片(以保留多态性)并保留封装,请在基类中返回一个 const
引用。
class Garage {
Vehicle & v_;
public Garage(Vehicle & v) : v_(v) {}
public const Vehicle& getVehicle() const { return v_; }
^^^^^ ^ ^^^^^
}
放弃 b_
等。在子类中,即
class BoatGarage : public Garage {
public BoatGarage(Boat & b) : Garage(b) {}
}
要允许派生类操作对象,请使用 protected 非常量版本重载 getVehicle
:
protected Vehicle& getVehicle() { return v_; } //This is in class Garage
你应该拥有你需要的一切。
关于c++ - 您如何设计一个具有基类成员的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25001454/