我对面向对象设计有疑问。
假设我们有一个可以包含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,一个用于车库?
为同一车辆创建2个引用是否有意义?就像在这种情况下,我有一个车辆参考和船参考同一条船。这是多余的吗?
编辑:澄清:我面临的最初问题是我只想要一种非常通用的方式来处理车库和车辆。我只是尝试用C ++练习OOP。我想我希望Vehicle基类能够随时添加车辆。我创建了一个Garage基类,因为也许我想添加一些函数,比如" paint boat"或" fix_tire"知道其类型
对车辆进行修改答案 0 :(得分:2)
类层次结构应该只包含一个对象的引用。为避免切片(保留多态性)并保留封装,请在基类中返回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) {}
}
要允许派生类操作对象,请使用受保护的非const版本重载getVehicle
:
protected Vehicle& getVehicle() { return v_; } //This is in class Garage
你应该拥有所需的一切。
答案 1 :(得分:1)
class BoatGarage : public Garage {
public BoatGarage(Boat & b) : Garage(b), b_(b) {}
public Boat & getBoat() const { return (Boat &)_v; }
}
我建议改用BoatGarage消除了对船的额外参考。由于您知道 _v
实际上属于Boat
类型,因此您可以将其强制转换并避免将第二个引用存储到Boat
。
另请注意,我将getBoat()
作为const
方法。你也可以这样做getVechicle()
。
答案 2 :(得分:0)
使用C++11,你可以为会员使用std::shared_ptr(或其他一些智能指针),然后它可以"是" (即指向)基类。
请注意,子类不能有一个直接作为其超类的字段,否则它将直观地需要一个无限的内存(它的sizeof
将是无限的)。当然,该字段可以是原始指针,引用或智能指针。