【问题标题】:Extending base class and using the feature without altering the derived classes扩展基类并使用特性而不改变派生类
【发布时间】:2020-03-25 13:09:54
【问题描述】:

我有一个带有一些派生类的 C++ 基类。如果我稍后通过继承扩展基类,它可以反映已经派生类中的更改。为了让我的问题更清楚,请考虑以下代码。

#include <iostream>

class FourWheelVehicle
{
    public:
        FourWheelVehicle()
        {std::cout<<"FourWheelVehicle created\n";}
};
class Car: public FourWheelVehicle
{
    public:
        Car()
        {std::cout<<"Car created\n";}
};
class Toyota: public Car
{
    public:
        Toyota()
        {std::cout<<"Toyota Car created\n";}
};
class Audi: public Car
{
    public:
        Audi()
        {std::cout<<"Audi Car created\n";}
};
int main()
{
    Toyota t;
    std::cout<<"..............................\n";
    Audi a;
    return 0;
}

如何将 FourWheelVehicle 扩展到 FourWheelVehicleWithSeatBelt,以便我之前派生的所有汽车都可以在不更改代码的情况下获得安全带? 我尝试了以下方法:

           FourWheelVehicle
               /      \
              /        \
             /          \
            Car          \
            /\            \
           /  \            \
      Toyota Audi    FourWheelVehicleWithSeatBelt

class FourWheelVehicleWithSeatBelt: public FourWheelVehicle
{
    public:
        FourWheelVehicleWithSeatBelt()
        {std::cout<<"FourWheelVehicleWithSeatBelt created\n";}
};

上面的方案好像不行!

【问题讨论】:

  • 您说“所有”派生类都应该得到更改,那么为什么要创建一个新类呢?只需将安全带添加到FourWheelVehicle
  • @JaMiT:很抱歉造成混乱。我想完整地保留 FourWheelClass,以便有人可以选择带或不带安全带的汽车!同时,我不想写所有的子类,因为代码在所有类中都是一样的!
  • 为什么不创建一个基类 seatBelt 并从 FourWheelVehicle 和 SeatBelt 派生新类? : 奔驰: public FourWheelVehicle, SeatBelt { ... 正如@Frontoge 建议的那样

标签: c++ c++11 inheritance polymorphism


【解决方案1】:

类不继承自兄弟类。在您的图表中,期望Car 获取FourWheelVehicleWithSeatBelt 的特征就像期望Toyota 获取Audi 的特征一样。它不会发生。

要在您的继承链中获得另一个类,新类需要进入链中,而不是新分支中。由于您(出于某种原因)无法更改派生类,它们仍必须继承自 FourWheelVehicle。这会让您看到类似以下内容:

                  ????
                   /
                  /
                 /
           FourWheelVehicle
               /
              /
             /
            Car
            /\
           /  \
      Toyota Audi

对此有一种直截了当的方法。将您当前的 FourWheelVehicle 类重命名为其他名称 (FourWheelVehicleWithoutSeatBelts?),然后创建一个继承自 FourWheelVehicleWithoutSeatBelts 的新 FourWheelVehicle 类并添加安全带。或者新的FourWheelVehicle 应该继承自FourWheelVehicleWithoutSeatBeltsVehicleWithSeatBelts 类。也许Vehicle 会是这个方案中的一个虚拟基类。

命名方案很奇怪,但是由于您无法更改派生类的代码,因此您可能会被它所困扰。这是从不充分的设计开始的危险之一。 (请注意,“不足”并不总是设计师的错。有时是,但有时项目需求会发生不可预测的变化。)

(就我个人而言,我会尝试获得更改Car 定义的许可,以便可以使用更合理的命名方案。Car 的子代不需要更改。有时好的程序设计意味着与其他人交谈。)

【讨论】:

    【解决方案2】:

    好吧,在这种情况下,如果所有派生类都需要它,我不确定为什么您需要避免修改基类。但是,如果您仍然想这样做,您可以使用多重继承,例如:

    #include <iostream>
    
    class FourWheelVehicle
    {
        public:
            FourWheelVehicle()
            {std::cout<<"FourWheelVehicle created\n";}
    };
    class SeatBelt
    {
        public:
            SeatBelt()
            {std::cout<<"Seatbelt created\n";}
    };
    
    class Car: public FourWheelVehicle, SeatBelt
    {
        public:
            Car()
            {std::cout<<"Car created\n";}
    };
    

    这将通过公共继承将安全带和 FourWheelVehicle 分配给 Car

    【讨论】:

    • 我不认为这是 Soo 想要的,因为这样派生类被改变了
    猜你喜欢
    • 2013-04-27
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 2020-03-24
    相关资源
    最近更新 更多