C ++:在派生类中扩展成员类型

时间:2017-11-02 16:18:26

标签: c++ inheritance

我欢迎一些C ++继承方面的帮助,以便更好地掌握这个概念。 是否有可能扩展"创建派生类时的成员类型?我认为我的问题可以通过一个简单的例子得到最好的证明,我想用新的双变量扩展类 VehicleData

class VehicleData {
 int yearOfManufacture;
 //Different routines, for example Serialize(), etc., warranting to create a class for just a bunch of variables
};

class BicycleData:VehicleData {
 double frameHeight; //new property that only applies to bicycles
};

//Now I create the actual classes that use the types above
class Vehicle {
 VehicleData data;
 void PrintData(); //a function that works on basic vehicle data
};

class Bicycle:Vehicle {
 BicycleData data; //should copy VehicleData when creating an instance of this class
};

这种方法的问题在于,当我对上面的代码进行编码并创建一个Bicycle实例时,其BicycleData成员隐藏了现有的VehicleData成员。

有没有办法扩展基类,即只需添加一个新的双变量(在此示例中存储帧高度),并保留已存在的(制造年份)数据? / p>

2 个答案:

答案 0 :(得分:1)

简短回答;不是你想要的方式,但你可以达到类似的目的。

如果您将数据作为指针,则不要声明您拥有的实例。然后,您可以让BicycleData继承VehicleData,然后只需将数据替换为Bicycle的构造函数中的新实例。

class Vehicle {
  void PrintData();
  protected:
    void replaceData(std::shared_ptr<VehicleData> d) {
      data = d;
    }

    std::shared_ptr<VehicleData> getData() {
      return data;
    }

    template<class T>
    std::shared_ptr<T> getDataAs() {
      return std::dynamic_pointer_cast<T>(data);
    }
  private:
    std::shared_ptr<VehicleData> data;
};

class Bicycle:Vehicle {
  Bicycle(){replaceData(std::make_shared<BicycleData>());}

  std::shared_ptr<BicycleData> getData() {
    return getDataAs<BicycleData>();
  }  
};

答案 1 :(得分:1)

据我所知,没有干净的方法可以完全你想要的只有继承。

您可以从基类中创建模板:

template <typename Data>
class BaseVehicle
{
    Data data;
// etc.
};

class Vehicle : BaseVehicle<VehicleData>
{
// etc.
};

class Bicycle : BaseVehicle<BicycleData>
{
// etc.
};

然后,VehicleBicycle类将分别包含dataVehicleData类型的BicycleData字段。

因为在您的示例中,BicycleVehicle 私下继承(即不支持通过指针/引用Bicycle多态地使用Vehicle }),这实际上与你想要达到的目标相同。

如果你想要动态多态,你应该创建一个单独的,最好是抽象的类,为你的车辆定义接口,例如:

class VehicleInterface
{
public:
    // Some pure virtual interface methods
    virtual void moveTo(const Vector2 position) = 0;

    virtual ~VehicleInterface() = default;
};

然后你可以让你的混凝土车辆继承并实现这个界面:

class Vehicle : BaseVehicle<VehicleData>, public VehicleInterface
{
public:
    virtual void moveTo(const Vector2 position) override
    {
        // implementation for Vehicle
    }
};

class Bicycle : BaseVehicle<BicycleData>, public VehicleInterface
{
public:
    virtual void moveTo(const Vector2 position) override
    {
        // implementation for Bicycle
    }
};

然后,任何希望以多态方式使用车辆的函数都可以接受引用或指向VehicleInterface的指针:

void driveToWork(VehicleInterface* vehicle)
{
    vehicle->moveTo(getWorkPosition());
    // etc.
}