C++ Convert pointer from one derived class to another - c++

Say i have a class shape and 2 derived classes circle and square. The code is:
Shape* s1 = new circle;
Now I want to asssigne s1 to square, while preserving the variables that are common to both.
Shape* s1 = new Square;
How do i do this?

By using a constructor that takes a reference to the base class, you can easily copy the common Shape data:
#include <assert.h>
enum class Color { red, green, blue };
class Shape {
public:
Shape() : color(red) { }
void setColor(Color new_color) { color = new_color; }
Color getColor() const { return color; }
private:
Color color;
};
class Square : public Shape {
public:
Square() { }
// Using explicit constructor to help avoid accidentally
// using the wrong type of shape.
explicit Square(const Shape &that) : Shape(that) { }
};
class Circle : public Shape {
public:
Circle() { }
explicit Circle(const Shape &that) : Shape(that) { }
};
int main(int,char**)
{
Circle circle;
circle.setColor(Color::blue);
Square square(circle);
assert(circle.getColor()==square.getColor());
}

You can use your copy constructor :
Shape* s1 = new Circle;
Shape* s1 = new Square( s1 );
With :
class Square : public Shape
{
...
public:
Square( const Circle& rhs )
{
// Copy the value you want to keep
// Respect the rules of copy constructor implementation
}
// Even better :
Square( const Shape& rhs )
{
...
}
...
};
Don't forget that converting a Circle into Square is a bit weird.
And there is a memory LEAK in your implementation. If you don't want to use you Circle, delete it.
This would be better :
Shape* s1 = new Circle;
Shape* s2 = new Square( s1 );
delete s1;
EDIT : Here is a link about copy constructor and assignement operator : http://www.cplusplus.com/articles/y8hv0pDG/

Related

C++ Inheritance : Base attributes over various derived objects

I'm currently learning about C++ Inheritance, so if this question is a dumb one, I apologize in advance.
Implementing this scenario:
A super class has a color attribute, which can be any color (let's assume color is represented by an integer).
Let's assume I have an initialization of this super class, with the color red.
I am also going to initialize different objects of a sub-class which also share the color red.
My question is, is there any way that I can initialize this attribute color to red (or any color for that matter) and it would be automatically inherited by objects of it's sub-class, instead of setting the attribute to red every-time I initialize one of these objects?
Again apologies if I'm missing a basic concept here, but I can't seem to find anything online on this.
Pseudo-Code per request:
Super-class code:
class Shape {
int color;
Shape::Shape(int c) : color(c) { } //constructor
}
Sub-Class code:
class Square {
int length, width;
Square::Square(int l, int w, int c)
: length(l),
width(w),
color(c)
{ }
}
class Circle {
int radius;
Square::Square(int r, int c)
: radius(r),
color(c)
{ }
}
What I'm trying to say is that both square and circle need to have the same color, is there anyway (maybe from the super class? ) to declare this color (ex. red), and both shapes would have this color set the same?
You could accomplish what you want with a static default_color that gets used when no color is explicitly specified, and gets set whenever a color is specified.
struct Shape {
static int default_color;
int color;
Shape(int c) : color(c)
{
default_color = c;
}
Shape() : color(default_color) {}
};
Shape::default_color = BLACK;
struct Square : public Shape {
int length, width;
Square(int l, int w, int c)
: Shape(c),
length(l),
width(w),
{ }
Square(int l, int w)
: length(l),
width(w)
{ }
}
struct Circle : public Shape {
int radius;
Circle(int r, int c)
: Shape(c),
radius(r)
{ }
Circle(int r)
: radius(r)
{ }
}
int main()
{
Square sq(2, 3, RED);
Circle cir(10); // Automatically red, since that's
the last color explicitly specified
}
I would say this is a poor design though. Global state like this makes it very easy to make mistakes. You now have to think about the state of the entire program whenever you create a shape. It would be better to simply create the Circle as Circle cir(10, sq.color);. That makes it explicit what color your Circle is, and reduces cognitive load on the programmer.
Prior to C++11, the primary way to do this would be as follows:
class baseClass
{
int color;
baseClass() { color = RED; }
};
class subClass : public baseClass
{
subclass() { }
};
With C++11 and later, you can assign the default value in the class declaration:
class baseClass
{
int color = RED;
baseClass() { }
};
This would be inherited.
EDIT: As mentioned below, the default baseClass constructor is automatically called in this case.
There's a difference between a class and an instance of a class. A class is something like a structure, according to which further instances will be created. A class is something like a description, an instruction how to build objects. Inheritance is related to classes, not to objects. As for fields, the inherited class has all the same fields from the parent class plus some new fields you may add.
A simple example for you:
class MyBase {
public:
int color;
};
class MyChild : public MyBase {
public:
double length;
}
int main() {
MyBase myBaseObj;
myBaseObj.color = 1;
MyChild myChildObj;
myChildObj.color = 2;
myChildObj.length = 3.14;
return 0;
}
is there anyway (maybe from the super class? ) to declare this color (ex. red), and both shapes would have this color set the same?
In your posted example, yes. A super-class constructor can set its variables to whatever it wants to, for example:
Shape::Shape(int c) : color(7) { } // 7 == RED
If Shape had that constructor defined, then instances of every subclass would represent red shapes.
This sample program prints 7, overriding the user's chosen color:
#include <iostream>
class Shape {
public:
int color;
Shape(int c) : color(7) { } //constructor
};
class Square : public Shape {
public:
int length, width;
Square(int l, int w, int c)
: Shape(c),
length(l),
width(w)
{ }
};
class Circle : public Shape {
public:
int radius;
Circle(int r, int c)
: Shape(c),
radius(r)
{ }
};
int main() {
Square q(4,8,0);
std::cout << q.color << "\n";
}

Double dispatch and factory pattern

I've got the following code currently (not working):
#include <iostream>
#include <vector>
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
};
class Creator {
public:
virtual ~Creator() {};
virtual Shape* create() = 0;
virtual bool equals(Shape& s) { return false; };
};
class Circle : public Shape {
private:
Circle() : Shape() {};
public:
class CircleCreator : public Creator {
public:
virtual Shape* create() { return new Circle(); };
virtual bool equals(Shape& other_shape) { return false; };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {};
public:
class RectangleCreator : public Creator {
public:
virtual Shape* create() { return new Rectangle(); };
virtual bool equals(Shape& other_shape) { return false; };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
My goal is to use a factory pattern and avoid the creation of a new object if in a list I've got already that object. I tried to use a double dispatch pattern but it isn't easy to apply in this case. How can I do?
Edit: Since the code is used in a "critical" path, I want to avoid RTTI like dynamic_cast and so on.
Maybe something like this could do it using member variables
#include <iostream>
#include <vector>
enum
{
CIRCLE,
RECTANGLE
};
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
unsigned shapeType;
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
};
class Creator {
public:
unsigned shapeType;
virtual ~Creator() {};
virtual Shape* create() = 0;
bool equals(Shape& s) { return (this->shapeType == s.shapeType); };
};
class Circle : public Shape {
private:
Circle() : Shape() {shapeType=CIRCLE;};
public:
class CircleCreator : public Creator {
public:
CircleCreator() {shapeType=CIRCLE;};
virtual Shape* create() { return new Circle(); };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {shapeType=RECTANGLE;};
public:
class RectangleCreator : public Creator {
public:
RectangleCreator() {shapeType=RECTANGLE;};
virtual Shape* create() { return new Rectangle(); };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
or this - using virtual function to return type
#include <iostream>
#include <vector>
enum
{
CIRCLE,
RECTANGLE,
UNKNOWN
};
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
virtual unsigned iAmA(){return UNKNOWN;};
};
class Creator {
public:
virtual ~Creator() {};
virtual Shape* create() = 0;
virtual bool equals(Shape& s) { return false; };
};
class Circle : public Shape {
private:
Circle() : Shape() {};
virtual unsigned iAmA(){return CIRCLE;};
public:
class CircleCreator : public Creator {
public:
CircleCreator() {};
virtual Shape* create() { return new Circle(); };
virtual bool equals(Shape& other_shape) { return (CIRCLE == other_shape.iAmA()); };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {};
virtual unsigned iAmA(){return RECTANGLE;};
public:
class RectangleCreator : public Creator {
public:
RectangleCreator() {};
virtual Shape* create() { return new Rectangle(); };
virtual bool equals(Shape& other_shape) { return (RECTANGLE == other_shape.iAmA()); };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
I'm not sure what you're trying to do, but I guess this could point you some direction
enum class Shapes
{
Rectangle,
Circle,
...
};
class Shape
{
private:
Shapes m_shape;
protected:
Shape(Shapes shape)
{
m_shape = shape;
}
public:
Shapes GetShape() { return m_shape; } // this is used to check whether two shapes are equal
virtual ~Shape() = default;
};
And now for factory pattern you'd do:
class ShapeFactory
{
public:
static Shape* CreateShape(Shapes shape)
{
switch (shape)
{
case Shapes::Circle:
return new Circle();
// etc.
}
}
};
This feels very redundant and not very clever to me. Also, this can put alot of code into one place.
For the dispatch, you could do (I assume, I'm not really a fan of this concept as it can be made less verbose with a simple template use)
class ShapeCreator
{
public:
virtual Shape* Create() = 0;
virtual ~ShapeCreator() = default;
};
class Circle : public Shape
{
public:
class Creator : ShapeCreator
{
public:
Shape* Create() { return new Circle(); }
};
Circle() : Shape(Shapes::Circle)
{}
};
bool SomethingWithCircle()
{
Circle::Creator circleCreator;
Shape* first = circleCreator.Create();
Shape* second = circleCreator.Create();
// notice memleak here
return first->GetShape() == second->GetShape();
}
If using C++11, you can go even further and avoid the whole idea /which feels very java-like to me anyway/ using a proper template masturbation techniques. (Can still be applied to pre-C++11, you just won't be able specify the parameters.)
template<class T>
class ShapeCreator
{
public:
template<class... TParams>
static T* Create(TParams&&... parameters) { return new T(std::forward<TParams>(parameters)...); }
};
class Rectangle : public Shape
{
private:
int m_width;
int m_height;
public:
Rectangle(int width, int height) : Shape(Shapes::Rectangle)
{
m_width = width;
m_height = height;
}
};
bool DoSomethingWithRectangles()
{
Rectangle* first = ShapeCreator<Rectangle>::Create(10, 15);
Shape* second = ShapeCreator<Rectangle>::Create(20, 25);
// notice memleak here
return first->GetShape() == second->GetShape();
}
TL;DR
You don't really need RTTI but you need to store the type info somewhere in the base type. I'm using the enum Shapes for this.
Both Factory and Dispatch may seem as a good idea, but you will still need dynamic casting somewhere when using them.
You can replace those two patterns using templates, but as soon as you'll get a vector of the base objects, you'll still have to dynamic_cast at some point.
I didn't measure this whatsoever, but I'm really interested in performance comparison of using virtual functions and dynamic cast as I imagine they'd be very similar...
End note:
Please notice, that I personally feel that using methods like equals or operator== on classes defining the basic interface is not very wise, since there are two possible outcomes:
The equals is virtual -> slow but acceptable
The equals is not virtual -> cannot be used in inherited types to actually do more advanced/relevant comparison, breaking the idea of Open to extension, closed for modification
Obviously, if you don't define the equals, you'd have to write comparison code every time. Or possibly use some templated Comparison class with possible specializations through traits yielding again the best performance with no code duplicity.
Generally speaking, you can get to point where you'd ask yourself "why isn't there base object and reflection like in java or c# in c++? It would allow me to use all these nice and clever patterns." The answer is templates. Why do it run-time, when you can do it compile time?

C++ polygon rectangle and triangle inheritance

I am trying to make a Polygon class and a Rectangle and Triangle that inherit the first. Polygon class has height and width variables that I want them to be be given values within the constructor. Then, Rectangle and Triangle have area calculation methods. Then, I use a main() to give some examples. I use:
#include <iostream>
using namespace std;
class Polygon {
public:
Polygon(int, int);
protected:
int height;
int width;
};
class Rectangle: public Polygon {
public:
void calc_area();
};
class Triangle: public Polygon {
public:
void calc_area();
};
Polygon::Polygon(int a, int b) {
height = a;
width = b;
}
void Rectangle::calc_area() {
cout << "Rectangle area: " << (height*width) << endl;
}
void Triangle::calc_area() {
cout << "Triangle area: " << (height*width/2) << endl;
}
int main() {
Rectangle s1(5, 2);
Triangle s2(5, 2);
s1.calc_area();
s2.calc_area();
}
But while everything looks ok to my newbie eyes, I get a series of errors:
12 base Polygon' with only non-default constructor in class without a constructor `
36 no matching function for call to `Rectangle::Rectangle(int, int)
37 no matching function for call to `Triangle::Triangle(int, int)'
Can someone give me some tips? As seen, I am very new to C++...
You shouldn't call constructor to use ., such as:
Rectangle s1;
Triangle s2;
s1.Polygon(5, 2);
s2.Polygon(5, 2);
try this way:
Rectangle s1(5, 2);
Triangle s2(5, 2);
and you should add constructor for Rectangle and Triangle respectively:
class Rectangle: public Polygon {
public:
Rectangle(int height, int width):Polygon(height, width){}
void calc_area();
};
class Triangle: public Polygon {
public:
Triangle(int height, int width):Polygon(height, width){}
void calc_area();
};
To construct Triangle and Rectangle you are calling their invisible default constructors.
So the Triangle() and Rectangle() methods. These are implemented as empty methods, but they must also call the default constructors of any class they inherit from. So effectively this is the code that's being generated:
Triangle() : Polygon() {}
Rectangle() : Polygon() {}
Polygon will not get a default constructor because you created your own constructor. So the only way to get that back is to define it:
Polygon() {}
Or in C++11:
Polygon() = default;
The default constructor Triangle() or Rectangle() are called when you instantiate the member variable. So these lines are calling constructors:
Rectangle s1;
Triangle s2;
Note that once they are constructed they cannot be reconstructed. So these calls are illegal:
s1.Polygon(5, 2);
s2.Polygon(5, 2);
Now if you want to accomplish having a setting constructor, you can do that, but you'll need to define it for Triangle and Rectangle:
Triangle(int width, int height) : Polygon(width, height) {}
Triangle(int width, int height) : Polygon(width, height) {}
Again recall that defining these methods will cause your default constructor not to be generated for Triangle or Rectangle. So your s1 and s2 declarations will now be illegal, but that's OK cause you want to declare them with your new constructors anyway:
Rectangle s1(5, 2);
Triangle s2(5, 2);
You must use this way...
Rectangle *s1 = new Rectangle;
s1->ab(5,2);
s1->calc_area();

How to call different derived classes in constructors of classes derived from a different base class

In C++, I have two separate base classes, each of whose derived classes are somewhat coupled. Here's an example for the kind of thing I'd like to do:
First define a set of classes, e.g.,:
class Shape
{
public:
double area;
double diameter;
};
class Rectangle : public Shape
{
public:
double width;
double height;
};
class Circle : public Shape
{
public:
double radius;
};
The second set of classes then pertains to operations being performed on this first set of classes, something like this:
class Calculator
{
public:
static Calculator *create_calculator(shape *shape,const char *shape_type); // the factory
virtual void calculate()=0; // the actual calculation
};
class area_circles : public Calculator
{
class circles *circle;
public
area_circles(circles *circle)
{
this->circle = circle;
}
void calculate()
{
this->area = PI*pow(circle->radius,2);
}
}
class area_rectangles : public Calculator
{
class rectangles *rectangle;
public
area_rectangles(rectangles *rectangle)
{
this->rectangle = rectangle;
}
double calculate()
{
this->area = rectangle->height * rectangle->width;
}
}
Calculator *Calculator::create_calculator(shape *shape, const char *shape_type)
{
if (shape_type=="circle")
return new area_circles(shape);
if (shape_type=="rectangle")
return new area_rectangles(shape);
}
Then, the idea would be to call all this using something like:
rectangles *my_rectangle;
Calculator *area_calculator;
area_calculator = area_calculator->create_calculator(my_rectangle, "rectangle");
area_calculator->calculate();
However, this doesn't compile and I get an error (quite sensibly) pointing out how the Shape class has no member "width", and that "a value of type "shape *" cannot be assigned an entity of type "rectangles". The error's pretty clear on why this code isn't working.
Would anyone know how to get the code here to do what I'm trying to do?
From a design perspective, I recognize that part of the problem is that the derived classes end up being coupled, so maybe there is a better way to try to decouple the calculator class from the shape class. But I'd like to at least try out this approach for a while as well in my implementation, and for that I need the code to compile.
I am not entirely sure what you are trying to achieve here but I think the more usual approach to it is something like this:
class Shape
{
public:
virtual ~Shape() {}
// concrete classes must implement this function
virtual double get_area() const = 0;
};
class Circle
: public Shape
{
double diameter;
public:
Circle(double diameter): diameter(diameter) {}
virtual double get_area() const
{
return M_PI * diameter * diameter / 4;
}
};
class Rectangle
: public Shape
{
double width;
double height;
public:
Rectangle(double width, double height): width(width), height(height) {}
virtual double get_area() const
{
return width * height;
}
};
int main()
{
Circle c(2);
Rectangle r(20, 40);
// use Shape references (or pointers) to invoke polymorphic behaviour
Shape& cs = c;
Shape& rs = r;
std::cout << "Area of circle : " << cs.get_area() << '\n';
std::cout << "Area of rectangle: " << rs.get_area() << '\n';
}

Initialize Objects as Class Members in C++

There are three classes.The first is a template, the second acts as generic for template and third implements the template.
template <class T>
class Shape {
T val,val_new;
public:
Shape(T initval)
{
val=initval;
}
...
};
class TwoPoint
{
int width;
int value;
public:
TwoPoint()
{
value=0;
width=0;
}
TwoPoint(int v, int w)
{
value=v;
width=w;
}
TwoPoint(const TwoPoint& t)
{
value= t.value;
width= t.width;
}
...
};
class Rectangle
{
private:
Shape<TwoPoint> val;
TwoPoint newval;
public:
Rectangle(TwoPoint i)
: val (Shape<TwoPoint> (i)) {}
....
};
I want to initialize the Rectangle and solidShape in some other class as class members and that can be done in java like:
Rectangle r = new Rectangle(new TwoPoint(0,8));
Shape<TwoPoint> solidShape = new Shape<TwoPoint>(new TwoPoint(0,5));
How can i do a similar type of thing in C++? I want to create an implementation like:
class C
{
public:
// initialize Rectangle here;
// initialize solidShape here;
}
The integer values shown here are just for illustration and can be anything.
The correct way to have a conversion constructor in C++ is through a const reference:
Rectangle(const TwoPoint& i)
This also means you can pass a temporary as parameter:
Rectangle* r = new Rectangle( TwoPoint(0,8) ); //dynamic storage
or
Rectangle r( TwoPoint(0,8) ); //automatic storage
It would also work with a pass by value, but this is the standard way of doing it.
Same goes for the Shape class:
Shape(const T& initval) //conversion constructor
and:
Shape<TwoPoint>* solidShape = new Shape<TwoPoint>( TwoPoint(0,5) ); //dynamic storage
or
Shape<TwoPoint> solidShape( TwoPoint(0,5) ); //automatic storage
In C++, new returns a pointer. But your conversion constructors take objects (not pointers to objects) by reference or value. So you need an object passed as parameter, not pointers.
If these two are class members:
if you chose to have pointers, you need to free the memory in the destructor.
if you chose automatic storage objects (what you have now), the destructors will be called when the containing object is destroyed, so you don't manually free the memory. To initialize automatic storage objects that are class members, you need to use an initialization list:
Like this:
class C
{
Shape<TwoPoint> solidShape;
Rectangle r;
public:
C() : solidShape(TwoPoint(0,5)), r( TwoPoint(0,8) ) {} //initialization list in constructor
};
We use const references as constructor parameters and initialization constructor chain:
template <class T>
class Shape {
T val,val_new;
public:
Shape(const T & initval) :
val(initval)
{
}
...
};
class TwoPoint
{
int width;
int value;
public:
TwoPoint() :
value(0),
width(0)
{
}
TwoPoint(int v, int w) :
value(v),
width(v)
{
}
TwoPoint(const TwoPoint& t)
value(t.value),
width(t.width)
{
}
...
};
class Rectangle
{
private:
Shape<TwoPoint> val;
TwoPoint newval;
public:
Rectangle(const TwoPoint & i)
: val (Shape<TwoPoint> (i))
{}
....
};
and you create object like this:
TwoPoint t(0,8)
Rectangle r(t);
Shape<TwoPoint> shape(t);