I have a project using the CImg library. What I have to do is declare classes that inherit from an abstract base class called shape. These classes are classes for the different shapes(circle, rectangle .. etc). What I want to do is use a struct class called point for the different points that I need for every class. So for example, for a triangle shape, I have to use three points to draw a triangle with each point having an x coordinate and a y-coordinate. So here's what I got so far.
class Shape
{
public:
virtual void draw_shape() = 0;
virtual double area() = 0;
};
struct Point
{
const int x; //const is necessary because CImg drawing functions require them.
const int y;
};
class Triangle : public Shape
{
private:
struct Point first;
struct Point second;
struct Point third;
public:
Triangle();
Triangle(const int, const int, const int, const int, const int, const int);
virtual void draw_shape();
virtual double area();
};
1) How do I initialize the x-coordinate and y-coordinate of each struct ?
Triangle::Triangle() : first.x(0), first.y(0), second.x(0), second.y(0), third.x(0), third.y(0)
does not work
2) Is my overloaded constructor correct or should I use this constructor:
Triangle(Point, Point, Point);
3) How do i use the points after this whenever I want to draw something ?!
4) Is the struct before instantiating the Points necessary in c++?
You can invoke the constructors of your points, like this:
Triangle() : first{0, 0}, second{0, 0}, third{0, 0} {}
You can add an explicit constructor yourself, if you wanted to do something a little more complex:
struct Point
{
int x;
int y;
Point(int a, int b) : x(a), y(b) { /* ... */ }
};
Considering 1)
You can simply use this:
Triangle::Triangle() : first{0,0}, second{0,0}, third{0,0} {}
Considering 2)
I think that the constructor
Triangle(Point, Point, Point);
is better. When you already have points, why not using them?
Considering 3)
dependons on how things get drawn
Considering 4)
No, it is not necessary.
Related
I am new to C++ and trying to make list polymorphic/accepting anything deriving from a base class. The issue is that this list must be private, using separate methods to append and interrogate it.
After some research, I was able to get close in a safe manner through smart pointers.
Here is what I have arrived at:
class Shape
{
public:
Shape(std::string name)
{
this->name = name;
}
std::string name;
std::string getName(void)
{
return this->name;
}
};
class ShapeCollector
{
public:
void addShape(Shape shape)
{
this->shapes.push_back(std::make_unique<Shape>("hey"));
}
private:
std::vector <std::unique_ptr<Shape>> shapes;
};
I would like to be able to replace the make_unique call with the shape parameter, however nothing I try seems to play correctly.
I could create each derived class inside ShapeCollector, mirroring the constructor arguments as parameters, but this feels very counter intuitive.
Any help would be appreciated!
Write addShape to take the derived class as a template parameter:
template<class Derived, class... Args>
void addShape(Args&&... args) {
// std::forward will correctly choose when to copy or move
std::unique_ptr<Shape> shape (new Derived(std::forward<Args>(args)...));
shapes.push_back(std::move(shape));
}
This will allow you to give addShape the arguments for the derived classs constructor. For example, if we have aCircle` class:
class Circle : public Shape {
double radius;
double x;
double y;
public:
Circle(double radius, double x, double y)
: Shape("circle"), radius(radius), x(x), y(y)
{}
};
Adding it is simple:
ShapeCollector shapes;
shapes.addShape<Circle>(10.0, 0.0, 0.0);
I want to create a class with a function that adds elements to a list that contains subclasses of an abstract superclass.
I have an abstract class "Shape" with multiple subclasses. In my example, I use the subclass "Circle" but there may be "Rectangle", "Polygon" or any other shape.
The ShapeList class looks (simplified) like this:
ShapeList.h file
#include "Shape.h"
class Node;
class ShapeList
{
public:
ShapeList() : first(0){};
void add( const Shape& s );
private:
Node *first;
};
ShapeList.cpp file
#include "ShapeList.h"
class Node
{
public:
friend ShapeList;
Shape *shapes;
Node *next;
Node( Node *n, Shape *s) : next(n), shapes(s){};
};
void ShapeList::add( const Shape& s ){
first = new Node(first, s);
}
Super Class Shape (also simplified)
class Shape
{
public:
Shape();
Shape(double x, double y) : posX(x), posY(y){};
protected:
virtual const double area() = 0;
double posX;
double posY;
};
Subclass Circle which is one of several subclasses
Circle.h file
#include <math.h>
#include <Shape.h>
class Circle : public Shape
{
public:
Circle();
Circle( double x, double y, double r) : Shape(x, y), radie(r){};
const double area();
private:
double radie;
};
Circle.cpp file
#include "Circle.h"
Circle::Circle()
: Shape(0, 0), radie(0)
{}
const double Circle::area(){
return radie * radie * M_PI;
}
Then I want to do, for example, somthing like this:
#include <iostream>
using namespace std;
#include "shapelist.h"
#include "Circle.h"
int main()
{
ShapeList list;
list.add( Circle( 5,5, 3) );
}
So the questions are:
How can I pass a subclass as an argument to a function with a superclass parameter? Is it possible? Create add functions for each shape and Template is not an option.
I have tested and changed a lot in add function but I do not get it working. What's wrong?
Just one note is that I have made changes so many times in the code that I may have destroyed something obvious in the code posted here. Can you point out the mistake?
Yes, it is possible to pass a subclass as an argument to a function that takes a superclass parameter but only if you pass by reference or by pointer. If you try to pass by value you experience object slicing.
But that is only part of the story. The next important question is about ownership. Who owns the Shape (and the Node for that matter). Who ensures it is deleted? The easiest way of managing ownership is to use automatic storage and then they will be automatically deleted when they go out of scope. In this case you could consider the possibility that the main function holds a Circle object that goes out of scope at the end of the function. You could pass this Circle as a Shape reference to the ShapeList and then the ShapeList is not responsible for deleting it.
int main() {
ShapeList list;
Circle c(5, 5, 3);
list.add( c );
}
However, looking through your code it looks like you have committed to the ShapeList owning Shape. In which case you have to worry about memory management. I warn you, manual memory management is hard to get right (I may have got it wrong below). If you must take ownership of objects by-pointer I strongly recommend using smart-pointers like std::unique_ptr. But let's assume you really want to do manual memory management.
It would be very unusual to pass ownership using a reference so I would change ShapeList::add to take a pointer. If ShapeList does not need to modify the Shape it could be a pointer-to-const:
void ShapeList::add( const Shape *s ){
first = new Node(first, s);
}
Then in the main function create the Circle using new:
int main() {
ShapeList list;
list.add( new Circle( 10, 10, 4) );
}
Now, ShapeList and Node need to worry about manual memory management so you need to consider the rule of three (five). At the very least you need to properly define the destructor for Node and ShapeList and prevent copy construction/assignment. Also Shape must have a virtual destructor in order to properly delete it.
There were a few other minor changes I had to make in order to compile the code without warnings but I'll leave that to you to find:
constexpr double PI = 3.141592653589793238463;
class Shape
{
public:
Shape();
Shape(double x, double y) : posX(x), posY(y){};
virtual ~Shape() {} // Important if a pointer-to-shape is being deleted!
virtual double area() const = 0;
protected:
double posX;
double posY;
};
class Node
{
public:
Node *next;
const Shape *shape;
Node( Node *n, const Shape *s) : next(n), shape(s){};
~Node() { delete next; delete shape; }
Node(const Node&) = delete; // Prevent copying to
Node& operator=(const Node&) = delete; // avoid double-deletion.
};
class ShapeList
{
public:
ShapeList() : first(nullptr) {};
~ShapeList() { delete first; }
ShapeList(const ShapeList&) = delete; // Prevent copying to
ShapeList& operator=(const ShapeList&) = delete; // avoid double-deletion.
void add( const Shape* s ){ first = new Node(first, s); }
private:
Node *first;
};
class Circle : public Shape
{
public:
Circle(): Shape(0, 0), radie(0) {}
Circle( double x, double y, double r) : Shape(x, y), radie(r){};
double area() const { return radie * radie * PI; }
private:
double radie;
};
int main() {
ShapeList list;
list.add( new Circle( 10, 10, 4) );
}
Another option, if you want to keep your main function looking like it does is for Shape to have a way of polymorphically copying itself to avoid object slicing. Typically, this is using a virtual clone function. Then ShapeList::add could take by-reference then take a "clone" to own internally.
Of course, in practice you don't need to write your own list class given that there is already std::list in the standard library. Putting this together with unique_ptr is simple.
I have a virtual class Shape. class Rectangle, Triangle, Circle inherit from Shape and have different characteristics (size, number of side...).
I want to store different shape in a structure (let's say a vector).
so my vector would be: vector<Shape*> myvec;
I would like to know how it is possible to know if a given instance of a shape is present in the vector (ex: new Circle(diameter 10);).
I have heard about dynamic cast but I don't understand at all how to use it?
class Shape
{
public:
Shape(){}
virtual int Size()=0;
virtual int Sides()=0;
virtual bool isequal(const Shape & rhs)=0;
int size,sides;
};
class Circle : public Shape
{
public:
Circle(int diameter):size(diameter)
{
sides=0;
}
bool isequal(const Circle &rhs)
{
return size==rhs.size;
}
int size,sides;
};
class Rectangle: public Shape
{
Rectangle(int nbsides,int size1,int size2 ): sides(nbsides),size1(size1),size2(size2){}
bool isequal(const Rectangle &rhs)
{
return (size1==rhs.size1 && rhs.size2==size2);
}
int sides,size1,size2;
};
dynamic_cast is right:
Shape* shape = myvec[0];
Circle* circle = dynamic_cast<Circle*>(shape);
if(circle != nullptr)
; // it's a Circle! Do something circly.
else
; // it's not a Circle. Do something else.
But a better answer to the question is that, in a perfect world, you should use polymorphism such that it is rarely if ever necessary to do this.
Based on the additional comments below, I think you might want to use a pure virtual isequal() in Shape, with dynamic_casts inside the various implementations (the inside of a polymorphic comparison function is one of the few places I can use dynamic_cast without feeling the need to wash my hands afterwards :) ).
// edited out code that isn't directly relevant
class Shape
{
public:
virtual bool isequal(const Shape& rhs)=0;
};
class Circle : public Shape
{
public:
// snip
virtual bool isequal(const Shape &rhs) override
{
Circle* rhsAsCircle = dynamic_cast<Circle*>(&rhs);
if(rhsAsCircle == nullptr)
return false; // not a Circle; can't be equal
return size==rhsAsCircle->size;
}
};
Then elsewhere:
Circle searchCircle(10);
for(Shape* shape : myvec)
if(shape->isequal(searchCircle))
; // we have a match!
Suppose we have an abstract class Element from which classes Triangle and Quadrilateral are derived from.
Suppose yet that these classes are used in conjunction with interpolation methods that depend on the shape of the element. So, basically we create an abstract class InterpolationElement from which we derive InterpolationTriangle and InterpolationQuadrilateral.
Then, to include the interpolation functionality in the Triangle and Quadrilateral classes, we add a const-reference data member in class Element of type InterpolationElement, that is:
class Element
{
public:
Element(const InterpolationElement& interp);
const InterpolationElement& getInterpolation() const;
private:
const InterpolationElement& interpolation;
};
We then create a method (as described by Scott Meyers, Effective C++) that instanciate a local static object of class InterpolationTriangle as
const InterpolationTriangle& getInterpolationTriangle()
{
static InterpolationTriangle interpolationTriangle;
return interpolationTriangle;
}
So that class Triangle can be constructed like:
class Triangle : public Element
{
public:
Triangle() : Element( getInterpolationTriangle() ) {}
};
Here is my question: is this approach correct in order to incorporate interpolation methods on my class Element? Is this used in professional scenarios?
I could implement directly all the interpolation methods on class Element (as pure virtual) and the override them in the derived classes Triangle and Quadrilateral. However, this approach seems to me to be cumbersome, since every time I need to improve or implement new interpolation functionalities I would have to do that on these classes. Moreover, the classes get bigger and bigger (many methods) using this approach.
I would like to hear from you some tips and comments
Thanks in advance.
Additional details:
class InterpolationElement
{
public:
InterpolationElement();
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
}
class InterpolationTriangle : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
class InterpolationQuadrilateral : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
:
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
The classes are used in conjunction with interpolation methods. Why do those methods need to be in a singleton object? The singleton here looks very problematic.
class Element
{
public:
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
};
class Triangle : public Element
{
public:
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
Also, welcome to SO!
This is reminiscent of a question that I had answered here. The same idea about the separation of data containers and the strategies.
There is one little issue with your proposal: you have added an interpolation related method to your base class and you've changed the constructor...
So first of all, if you wish to do it this way, here is how you should do it:
class Element
{
public:
private:
// similar signature to a `clone` method
virtual InterpolationElement* interpolation() const = 0;
};
class Triangle
{
public:
private:
virtual InterpolationTriangle* interpolation() const
{
return new InterpolationTriangle();
}
};
There are 2 advantages here:
It's no longer necessary to change the constructor of each of the derived objects
The strategy object is no longer const, which allows it to maintain state during the computation... like a reference to the current object being interpolated.
However, this still requires to change the Element class, and each of its derived classes. Doesn't it bother you ;) ?
Well, it's time (for once) to call upon a Design Pattern: Visitor.
It's a little different from the strategy idea, relying on double dispatch to work properly. However it allows you to tweak the hierarchy of Elements ONCE (with an accept method) and then to add as many operations as you wish. And that is great.
You can always mess a little bit with templates.
First we have a top class.
class Element {
public:
virtual void calculate() const = 0;
};
... but then we also have a class in the middle of the hierarchy which is actually a template. Template can't be the top level class, as templates with different parameters are different classes. The idea is that we give an interpolation class as a type parameter to the element.
template <typename Interpolation>
class Element_Impl : public Element {
protected:
Interpolation m_interpolation;
};
And interpolation classes. Notice, they aren't siblings, because they don't need to.
class InterpolationTriangle {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
And finally the real elements and the small main procedure.
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
m_interpolation.interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
m_interpolation.interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
Summary:
you can easily switch interpolation class for each element if needed.
there aren't double vtable access (first for Element's calculate and then for InterpolationElement's intepolate methods) as in the Matthieu's example. Each element knows at compile time which interpolation class it is using.
Element_Impl is an ugly bit, but it saves us from copypasta. You can expand it even further by implementing interpolation method wrappers
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
One way is to use static methods, and defining a wrapper in Element_Impl - still only in one place.
class Element {
public:
virtual void calculate() const = 0;
};
template <typename Interpolation>
class Element_Impl : public Element {
protected:
void interpolate(double, double) const {
Interpolation::interpolate(1, 1);
}
};
class InterpolationTriangle {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
What first comes to my mind is the GoF Design Pattern Visitor
From what I understand of your problem, this pattern is conceived to exactly solve this issue.
Each Visitor object defines an interpolation technique, or an algorithm to apply to your object.
Thus the Element class doesn't grow at all with each new functionnality. Once in place, the Visitor pattern enables to enrich functionnality without touching to the Base class definition.
I need a way for a single variable to represent two kinds of objects derived from the same base class.
It's kinda hard to describe but I'll try the best:
Say the base class:
class Rectangle
{
float w;
float h;
const float area() {return w*h;}
};
And the two derived classes:
class Poker : Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : Rectangle
{
string name;
string address;
string phone;
};
Now is it possible to declare an object, which could be either a poker or a business-card?
'cuz the usage below is illegal:
Rectangle* rec;
rec = new Poker();
delete rec;
rec = new BusinessCard();
Polymorphism might be a way but since it's only good for changing base-class' member attributes, I need this object to be able to represent exactly either of the derived objects.
EDIT:
Thanks for the all the answers. The public inheritance , the virtual destructor and even the boost::variant typedef are all fantastic hints.
You can do that. The problem is the inheritance modifier for classes is private. Most of the time, private inheritance is not what you want to use. Instead, declare it explicitly as public:
class Rectangle
{
float w;
float h;
const float area() {return w*h; }; // you missed a semicolon here, btw
virtual ~Rectangle() { } // to make `delete` work correctly
};
class Poker : public Rectangle // note the public keyword
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
Then your code snippet should work.
You need to change the qualifier for the inheritence to public.
class Poker : public Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
is what you want. Now both classes, BusinessCard and Poker are of type Rectangle.
I need this object to be able to
represent exactly either of the
derived objects.
Don't know if I understand it correct but have a look at boost::variant
typedef boost::variant<Poker, BusinessCard> PokerOrBusinessCard
Now you can access the derived classes with a boost variant visitor class.
Maybe this can be a solution.
I think what you may be looking for is multiple inheritance, where an object can sometimes be a Poker and sometimes a BusinessCard.
See here for a tutorial:
http://www.deitel.com/articles/cplusplus_tutorials/20060225/MultipleInheritance/index.html
Note that you can decide to make it one or the other if you wish, it does not have to be both all of the time, which may satisfy what you need.
Change the subclasses to use public derivation and your code works, with some cleanup. You should also use virtual destructors so the delete works correctly.
class Rectangle
{
float w;
float h;
const float area()
{
return w*h;
}
public:
virtual ~Rectangle(){};
};
class Poker : public Rectangle
{
int style; // Diamond, Club, .... int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};