У меня возникла проблема с виртуальным методом при попытке кода из https://en.wikipedia.org/wiki/Bridge_pattern < / а>.

Сообщения об ошибках:

Чистый виртуальный метод
terminate вызывается без активного исключения
Прервано (ядро сброшено)

Код был скомпилирован с помощью g ++ -o bridge bridge.cpp -std = c ++ 11
Почему drawing_api_.DrawCircle () вызвал виртуальную функцию в DrawingAPI?

#include <iostream>
#include <string>
#include <vector>


class DrawingAPI {
  public:
    virtual ~DrawingAPI() = default;
    virtual std::string DrawCircle(float x, float y, float radius) const = 0;
};

class DrawingAPI01 : public DrawingAPI {
  public:
    std::string DrawCircle(float x, float y, float radius) const override {
      return "API01.circle at " + std::to_string(x) + ":" + std::to_string(y) +
        " - radius: " + std::to_string(radius); 
    }
};

class DrawingAPI02 : public DrawingAPI {
  public:
    std::string DrawCircle(float x, float y, float radius) const override {
      return "API02.circle at " + std::to_string(x) + ":" + std::to_string(y) +
        " - radius: " + std::to_string(radius); 
    }
};

class Shape {
  public:
    Shape(const DrawingAPI& drawing_api) : drawing_api_(drawing_api) {}
    virtual ~Shape() = default;

    virtual std::string Draw() const = 0;
    virtual float ResizeByPercentage(const float percent) = 0;

  protected:
    const DrawingAPI& drawing_api_;
};

class CircleShape: public Shape {
  public:    
    CircleShape(float x, float y, float radius, const DrawingAPI& drawing_api)
      : Shape(drawing_api), x_(x), y_(y), radius_(radius) {}

    std::string Draw() const override {
        return drawing_api_.DrawCircle(x_, y_, radius_);
    }

    float ResizeByPercentage(const float percent) override {
      return radius_ *= (1.0f + percent/100.0f);
    }
  
  private:
    float x_, y_, radius_;
};

int main(int argc, char** argv) {
  std::vector<CircleShape> shapes {
    CircleShape{1.0f, 2.0f, 3.0f, DrawingAPI01{}},
    CircleShape{5.0f, 7.0f, 11.0f, DrawingAPI02{}}
  }; 

  for (auto& shape: shapes) {
    shape.ResizeByPercentage(2.5);
    std::cout << shape.Draw() << std::endl;
  }

  return 0;
}
0
k0ala Xing 9 Апр 2021 в 05:50

1 ответ

Лучший ответ

Опубликованный код содержит ошибки - в частности, класс Shape содержит ссылку на объект DrawingAPI:

class Shape {
[...]

protected:
   const DrawingAPI& drawing_api_;
};

... но объект, на который он ссылается, является временным и уничтожается, как только конструкторы CircleShape внутри main() возвращаются.

Один из способов избежать ошибки - объявить объекты DrawingAPI01 и DrawingAPI02 таким образом, чтобы их время жизни длилось дольше, чем время жизни объектов CircleShape, которые ссылаются на них, например изменив main(), чтобы он выглядел так:

int main(int argc, char** argv) {
   DrawingAPI01 api01;   // declaring these up here keeps them valid
   DrawingAPI01 api02;   // until the end of main()

   std::vector<CircleShape> shapes {
      CircleShape{1.0f, 2.0f, 3.0f, api01},
      CircleShape{5.0f, 7.0f, 11.0f, api02}
   };

   for (auto& shape: shapes) {
      shape.ResizeByPercentage(2.5);
      std::cout << shape.Draw() << std::endl;
   }

   return 0;
}
1
Jeremy Friesner 9 Апр 2021 в 03:09