如何设计一个具有基类成员的对象?

时间:2014-07-28 18:06:23

标签: c++ oop

我对面向对象设计有疑问。

假设我们有一个可以包含Vehicle对象的Garage类。这些车辆可以是汽车或船只。 BoatCar都延伸Vehicle

class Garage {
    Vehicle & v_;

    public Garage(Vehicle & v) : v_(v) {}
    public Vehicle getVehicle() { return v_; }
}

但是,我希望车库的含量非常不同,具体取决于它所包含的车辆。所以我考虑制作两个名为BoatGarageCarGarage的子类,它们都扩展了Garage。

示例:

class BoatGarage : public Garage {
    Boat & b_;
    public BoatGarage(Boat & b) : Garage(b), b_(b) {}
}

我有几个问题。

  1. 通过在构造函数中使用引用作为参数我确保我没有创建另一个版本的船吗?如果构造函数为BoatGarage(Boat b) : Garage(b), b_(b),我会创建2份船;一个用于BoatGarage,一个用于车库?

  2. 为同一车辆创建2个引用是否有意义?就像在这种情况下,我有一个车辆参考和船参考同一条船。这是多余的吗?


  3. 编辑:澄清:我面临的最初问题是我只想要一种非常通用的方式来处理车库和车辆。我只是尝试用C ++练习OOP。我想我希望Vehicle基类能够随时添加车辆。我创建了一个Garage基类,因为也许我想添加一些函数,比如" paint boat"或" fix_tire"知道其类型

    对车辆进行修改

3 个答案:

答案 0 :(得分:2)

  1. 是的,你在这里写的是正确的。
  2. 实际上,这是一个糟糕的设计。在类中对同一个对象进行两次引用意味着通过一个引用访问对象的代码可以通过另一个引用突然发现对象已经改变了;它增加了模糊和混淆的可能性,随着你的程序变大,任何可能因这种歧义而产生的错误都可能会出现。
  3. 类层次结构应该只包含一个对象的引用。为避免切片(保留多态性)并保留封装,请在基类中返回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)

  1. 是的,这是对的,也是正确的。
  2. 这个怎么样
  3. 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将是无限的)。当然,该字段可以是原始指针,引用或智能指针。