在C ++中动态更改对象的基类

时间:2018-10-16 06:35:24

标签: c++ inheritance design-patterns

我有两个类Sensor1和Sensor2,它们从Sensor类继承。我正在基于运行时的某些条件创建Camera类,其基类应为Sensor1或Sensor2。有可能吗?

一种方法是在Camera中为Sensor创建一个指针成员,然后将其分配给Sensor1或Sensor2(基于条件),在这种情况下,对于Sensor的所有方法,我需要在Camera中创建方法(setResolution和changeMode )并调用相应的方法(我想避免这种情况)

class Sensor {
 public:
       Sensor(){}
       ~Sensor(){}
       void setResolution(int w, int h) {};
       void changeMode(int mode) {};
}

class Sensor1: public Sensor {
  public:
       Sensor1(){}
       ~Sensor1(){}
       void setResolution(int w, int h) {\** change based on sensor **\}
       void changeMode(int mode) {\** sensor specific implementation **\}
}

class Sensor2: public Sensor {
   public:
       Sensor2(){}
       ~Sensor2(){}
       void setResolution(int w, int h) {\** change based on sensor **\}
       void changeMode(int mode) {\** sensor specific implementation **\}

class Camera: public Sensor {
   public:
       Camera (bool flag){
       //Change base class to either Sensor1 or Sensor2 which inherits from common base class Sensor
       }
       ~Camera(){}
}

2 个答案:

答案 0 :(得分:4)

这是使用Strategy模式之类的好地方。

Sub Checkbox1_Click() Dim OutLookApp As Object Dim Mail As Object Dim subject_ As String Dim body_ As String subject_ = "Something" body_ = "Something else" If Sheets("Sheet1").CheckBox1.Value = True Then Set OutLookApp = CreateObject("Outlook.Application") Set Mail = OutLookApp.CreateItem(0) Application.DisplayAlerts = False With Mail .Subject = subject_ .Body = body_ .To = "email" .CC = "otheremail" .Importance = 2 .Send End With Application.DisplayAlerts = True End If End Sub 包含指向CameraCamera的指针,而不是更改Sensor1的基类。那是您检查病情的地方。

如果两个类Sensor2Sensor1继承自一个公共基础(例如Sensor2),则该模式很容易实现。

我的C ++有点生疏,因此请视其为代码还是伪代码而定,具体取决于其最终的有效性:

Sensor

您还可以提供函数(一个用于class Camera { private: Sensor* obj; public: Camera (bool flag){ if (flag) { obj = new Sensor1(); } else { obj = new Sensor2(); } } } ,另一个用于Sensor1),以将Sensor2字段转换为正确的类型。

关于更改基类

让我们谈谈为什么为什么无法切换基类,以及为什么即使可以也不能切换基类。

将您的类视为包含字段的普通结构,以及在该结构类型的名为obj的变量上运行的许多函数。

如果从this继承,则Sensor1的结构将包含Camera的所有字段和Sensor1的所有字段。为了论证,我们假设它们总共增加了42个字节的内存。假设将Camera中的字段与Sensor2中的字段组合起来,最多可增加60个字节。

很明显,如果您随后动态更改基本类型,则内存大小应该更改,但是在您进入构造函数时,分配已经完成。因此,如果您当时可以将基本类型从Camera切换到Sensor1,则突然会有18个字节太少,而更新其中任何一个都会覆盖可能分配给其他内容的内存。那是一场灾难,等待发生。

因此,我们使用了Strategy之类的模式,如我在此处所示。这样更容易推理,易于实施,被广泛理解并且安全。

答案 1 :(得分:1)

要使函数调用不进入Camera类,可以将同一任务委托给另一个类,例如SensorOperator。使Camera对象 Sensor对象组成。现在,如果出现任何新类,例如“移动”,它们可以具有相同的传感器,那么我们可以对其使用相同的策略。

template <typename T>
class SensorOperator : public Sensor {
private:
    T *t;
public:
    void setResolution(int w, int h) {
        t->setResolution(w, h);
    }
    void changeMode(int mode) { t->changeMode(mode); }
};
class Camera {
    public:
        Camera(bool flag) {
            //Change base class to either Sensor1 or Sensor2 which inherits from common base class Sensor
            if (flag) sensor = new SensorOperator<Sensor1>();
            else sensor = new SensorOperator<Sensor2>();

        }
        ~Camera() {}
    private:
        Sensor *sensor;
};

我更希望将Sensor类实现为抽象类。另外,在Camera类的情况下,更喜欢使用组合而不是继承,因为Camera可能不仅是Sensor,而且还有很多其他问题。