Reputation: 107
I got a virtual method problem when trying code from https://en.wikipedia.org/wiki/Bridge_pattern.
Error messages are:
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
The code was compiled with g++ -o bridge bridge.cpp -std=c++11
Why drawing_api_.DrawCircle()
called the virtual function in 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;
}
Upvotes: 0
Views: 52
Reputation: 73121
The posted code is buggy -- in particular, the Shape
class is holding a reference-to-a-DrawingAPI-object:
class Shape {
[...]
protected:
const DrawingAPI& drawing_api_;
};
... but the object that it is referencing is a temporary that gets destroyed as soon as the CircleShape
constructors inside main()
return.
One way to avoid the fault would be to declare the DrawingAPI01
and DrawingAPI02
objects in such a way that their lifetimes last longer than the lifetimes of the CircleShape
objects that reference them, e.g. by changing main()
to look like this:
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;
}
Upvotes: 1