Динамическое изменение базового класса объекта в C ++ - PullRequest
0 голосов
/ 16 октября 2018

У меня есть два класса Sensor1 и Sensor2, которые наследуются от класса Sensor.Я создаю класс Camera, для которого базовый класс должен быть Sensor1 или Sensor2 на основе некоторого условия во время выполнения.Возможно ли это?

Один из способов - создать элемент указателя для датчика в камере, а затем назначить для датчика 1 или датчика 2 (в зависимости от состояния), и в этом случае для всех методов датчика необходимо создатьметоды в 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 голосов
/ 16 октября 2018

Чтобы исключить вызовы функций из класса 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.

0 голосов
/ 16 октября 2018

Это отличное место, чтобы использовать что-то вроде шаблона Strategy .

Вместо изменения базового класса на Camera, пусть Camera содержит указатель либо на Sensor1, либо на Sensor2.Вот где вы проверяете свое состояние.

Если два класса Sensor1 и Sensor2 наследуются от общей базы (например, Sensor), шаблон очень прост в реализации.

Мой C ++ немного заржавел, поэтому воспринимайте это как код или псевдокод, в зависимости от того, насколько он действителен:

class Camera {
private:
  Sensor* obj;
public:
  Camera (bool flag){
    if (flag) {
      obj = new Sensor1();
    } else {
      obj = new Sensor2();
    }
  }
}

Вы также можете предоставить функции (одну для Sensor1 и одну для * 1020).*) для приведения поля obj к правильному типу.

Об изменении базового класса

Давайте поговорим о , почему это невозможнопереключить базовый класс и почему он был бы нецелесообразен, даже если бы вы могли.

Думайте о своем классе как о обычной структуре, содержащей поля, плюс ряд функций, работающих с переменной этого типа структуры с именем this.

Если вы наследуете от Sensor1, структура для Camera будет содержать все поля из Sensor1 и все поля из Camera.Ради аргумента, скажем, все это добавляет до 42 байтов памяти.И скажем, объединение полей из Sensor2 с полями из Camera добавляет до 60 байт.

Очевидно, что если вы затем динамически измените базовый тип, ваш объем памяти должен измениться, но распределение былоуже сделано, когда вы входите в конструктор.Таким образом, если бы вы могли переключать базовые типы с Sensor1 на Sensor2 в то время, у вас вдруг было бы слишком мало 18 байт, и обновление любого из них привело бы к перезаписи памяти, которая, возможно, была бы выделена для чего-то другого.Это катастрофа в ожидании.

И поэтому мы используем такие шаблоны, как Стратегия , как я показал здесь.Проще рассуждать, легко реализовать, широко понять и безопасно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...