Ссылка на реализацию без экземпляра

209
17 октября 2018, 17:10

Начал изучать книгу Эрика и Элизабет Фримен Паттерны проектирования. Пытаюсь написать на C++ архитектуру из первой главы.

Как в конструкторе наследника Duck (RedheadDuck) присвоить указателю FlyBehaviour FlyWithWings? В FlyWithWings одна статическая функция, и не хотелось бы создавать где-то в main()-е экземпляр, а потом передавать его в конструктор, можно ли как-то этого избежать?

Код:

class FlyBehaviour {
public:
  static virtual void fly() = 0;
};
class FlyWithWings : public FlyBehaviour {
public:
  static void fly() {
    cout << "I'm flying with wings!" << endl;
  }
};
class Duck {
private:
  FlyBehaviour *flyBehaviour;
public:
  virtual void display() = 0;
  void fly() {flyBehaviour->fly();}
};
class RedheadDuck : public Duck {
  RedheadDuck() {
    // Как присвоить flyBehaviour указатель на FlyWithWings?
  }
  void display() {
    cout << "I'm redhead duck." << endl;
  }
};

Всем спасибо, сделал так:

class FlyBehaviour {
public:
  virtual void fly() = 0;
};
class FlyWithWings : public FlyBehaviour {
public:
  void fly() {
    cout << "I'm flying with wings!" << endl;
  }
};
class Duck {
protected:
  FlyBehaviour *flyBehaviour;
public:
  Duck() {flyBehaviour = nullptr;}
  virtual void display() = 0;
  void fly() {flyBehaviour->fly();}
  ~Duck() {delete flyBehaviour;}
};
class RedheadDuck : public Duck {
public:
  RedheadDuck() {
    Duck::flyBehaviour = new FlyWithWings;
  }
  void display() {
    cout << "I'm redhead duck." << endl;
  }
};
Answer 1

Если я вас правильно понял, то так:

class RedheadDuck : public Duck {
  RedheadDuck(FlyBehaviour *in) : Duck{in} {
  }
  void display() {
    cout << "I'm redhead duck." << endl;
  }
};

Как видите, сдесь не хватает соответствующего конструктора для Duck

class Duck {
private:
  FlyBehaviour *flyBehaviour;
public:
  Duck(FlyBehaviour *in) : flyBehaviour{in}{};
  virtual void display() = 0;
  void fly() {flyBehaviour->fly();}
};

Если же вы не хотите каждый раз явно указывать при инициализации чем его нужно инициализировать, то установите аргумент по умолчанию:

RedheadDuck(FlyBehaviour *in = new FlyWithWings) : Duck{in}

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

Главное, раз уж работаете с указателями, предусмотрите освобождение памяти в деструкторе, либо используйте интеллектуальные указатели

Answer 2

Чтобы присвоить указатель на экземпляр FlyWithWings этот экземпляр сначала надо создать, а это сделать невозможно, так как это абстрактный класс, так как он не реализует метод fly. Встроенная система полиморфизма не допускает статических виртуальных методов. Так что static virtual void fly() = 0; является ошибкой синтаксиса. Делайте метод не статическим, реализуйте его в FlyWithWings, создавайте экземпляр FlyWithWings и присваивайте указателю адрес этого экземпляра. Если же никакого состояния хранить не требуется, то можно вместо указателя на класс использовать указатель на метод.

READ ALSO
Ошибка &ldquo;Could not determine Java version&hellip;&rdquo; Intelij Idea

Ошибка “Could not determine Java version…” Intelij Idea

Установил давно java10 и Intelij Idea, все прекрасно работалоВ один день при открытии Intelij Idea появилась ошибка

149
Как заморозить переменную в Java?

Как заморозить переменную в Java?

Есть вес кошки, есть максимальный и минимальный возможный вес, при выходе за пределы допустимого веса кошка умираетКак заморозить переменную...

147
Отправить изображения при регистрации

Отправить изображения при регистрации

Есть программа, которая позволяет пользователю войти и добавить продуктыПри регистрации отправляется линк для активации профиля это в email - е выглядит...

163