Why i am not able to cast pointer to the class structure - c++

I have a Geometry class
class Geometry
{
public:
std::string stdstrType;
bool bValid;
public:
Geometry()
Geometry( std::string strType , bool bValue )
Geometry(const Geometry &g)
~Geometry()
virtual void draw();
bool isValid();
void setValidState(bool bState);
virtual void Init();
std::string GetName();
};
Which is the base class for Geometry objects like in this case for Sphere class
class Sph : public Geometry
{
public:
Sph( float radius , float segments );
~Sph();
void init();
void CleanUp();
void draw();
private:
float fRadius, fSegments;
bool isInited;
unsigned int m_VAO, m_VBO;
int iNumsToDraw;
SumShader shader;
bool isChanged;
};
I have a Tree structure holding different Container objects and Geometry is a data type in the Container object.
class Container
{
private:
std::string stdstrContainerName;
std::string stdstrPluginType;
Geometry Geom;
}
Since each item in the tree can hold a circle sphere or rectangle so I would like to use the draw function of geometry to draw the Geometry object types.
For this when I try to cast any Geometry Object type to Geometry I get an error.
Sph sphere(0.1 , 32);
Geometry *geom = &sphere;
Container cont("Sphere" , "SPHERE" , *geometry );
myModel->SetContainer(child, cont);
The Constructor for Container
Container::Container( std::string strName, std::string strType, const
Geometry& geometry) : Geom(geometry)
{
stdstrContainerName = strName;
stdstrPluginType = strType;
}
void TreeModel::SetContainer(const QModelIndex &index, Container Cont)
{
TreeItem *item = getItem(index);
item->setContainer(Cont);
}
class TreeItem
{
public:
// Functions here
private:
QList<TreeItem*> childItems;
Container itemData;
TreeItem* parentItem;
};
1) Is this the correct approach?
2) How can I cast the Geometry objects to the Geometry pointer?

With
Sph sphere();
You have declared a function wich return a Sphere object and take no parameters.
To declare an object to Sph you just simple write
Sph sphere; or Sph sphere{};
I guess you tried the first but it didn't compile, so you just changed the signature "until compiled".
You have declared a custom constructor, which means the compiler does not provide you anymore a default constructor so you can't declare a variable without calling the correct constructor (and in your case it wouldn't have sense).
In addition with
Geometry *geom = new Geometry;
geom = &sphere;
you're creating a new pointer geometry than leaking it immediatly and reassigning to a sphere geometry which has no sense at all.
Moreover all your method are public in Geometry and this does not have sense (why putting bool valid public and then a getter?).
in addition class Container is holding an instance to a base class which will give you issues due to object slicing, you need to use a pointer or a reference.
for just answering to your question you should instance a sphere with
Geometr* geom = new Sphere(1, 5); // random numbers
but the most genuine and honest thing I can tell is to rewrite everything from scratch and before that to study a little more trying with an easier example.

The minimal code that works and implements an idea in the question:
#include <iostream>
class Geometry
{
public:
Geometry(const std::string type) { stdstrType = type; }
std::string GetName() { return stdstrType; }
virtual void draw() {} ;
private:
std::string stdstrType;
};
class Sphere : public Geometry
{
public:
Sphere(float radius): Geometry("Sphere ") { fRadius = radius; }
virtual void draw() { std::cout << GetName() << fRadius << "\n";}
private:
float fRadius;
};
class Container
{
public:
Container(std::string strName, Geometry* g)
{
stdstrContainerName = strName;
geometry = g;
}
void draw() { geometry->draw(); }
private:
std::string stdstrContainerName;
Geometry *geometry;
};
int main(int argc, const char * argv[]) {
Sphere sphere(0.1);
Geometry *geom = &sphere;
Container cont("Sphere container", geom);
cont.draw();
return 0;
}
Xcode 10.2.1: No Buildtime/Runtime Issues. Output:
Sphere 0.1
Program ended with exit code: 0

Related

Storing classes in boost::variant

Someone recommended me to use boost::variant as shape variable to store different types of shapes in it. But, when implemented boost::variant to my code, I got an error while compiling. Error says: 'Shape': base class undefined and more errors.
Here is my code (Object.h):
using Shape = boost::variant<Rectangle, Circle>;
enum Shape_Type
{
RECTANGLE,
CIRCLE
};
struct Position
{
float x, y;
Position(float position_x, float position_y)
{
x = position_x;
y = position_y;
}
};
class Object : private Shape
{
private:
std::string name;
public:
Object() = default;
Object(std::string name, Rectangle rectangle) : name(name), Shape(rectangle)
{
}
Object(std::string name, Circle circle) : name(name), Shape(circle)
{
}
void setPosition(float, float);
void setAngle(float);
Shape* getShape()
{
Shape* shape = this;
return shape;
}
Position getPosition();
const std::string* getName()
{
return &name;
}
};
class Rectangle
{
private:
sf::RectangleShape rectangleshape;
public:
Rectangle() = default;
Rectangle(float width, float height)
: rectangleshape(sf::RectangleShape(sf::Vector2f(width, height)))
{
}
void setPosition(float position_x, float position_y)
{
rectangleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
rectangleshape.setRotation(angle);
}
sf::RectangleShape* getRectangleShape()
{
return &rectangleshape;
}
Position getPosition()
{
return Position(rectangleshape.getPosition().x,
rectangleshape.getPosition().y);
}
};
class Circle
{
private:
sf::CircleShape circleshape;
public:
Circle() = default;
Circle(std::string name, float radius)
: circleshape(sf::CircleShape(radius))
{
}
void setPosition(float position_x, float position_y)
{
circleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
circleshape.setRotation(angle);
}
sf::CircleShape* getCircleShape()
{
return &circleshape;
}
Position getPosition()
{
return Position(circleshape.getPosition().x,
circleshape.getPosition().y);
}
};
And btw is getShape() function good?
Variants are used for static polymorphism, so you don't need the base class at all (that's dynamic - or virtual - polymorphism).
The members in a variant typically do not share a common base class, so you wouldn't have the getShape function, or you'd need to template it:
template <typename T>
T const& getShape() const { return boost::get<T>(_shape); }

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?

Using inherited function instead of the base (not abstract)

I want to have classes named chessman and pawn, for example. I can't make chessman an abstract class because I need to create an 2D array of it. pawn class inherits chessman and I need to use move function of pawn when I write this:
chessman *cm = new pawn("a3", 'w');
cm->move(pos);
This code uses chessman::move. What can I do to make it use the one from pawn class? My question is very similar to this question, but my function doesn't take pawn as an argument. In Java, it's easy since you can create arrays of abstract classes, but in C++ it is just confusing.
EDIT:
Here is definition of chessman class (function already is virtual as you can see):
class chessman
{
public:
int i;
int j;
string name;
char color;
virtual bool move(string final_pos);
};
And pawn:
class pawn : public chessman
{
public:
pawn(string pos, char color);
bool move(string final_pos);
};
I can't make chessman an abstract class because I need to create an 2D array of it.
Yes, you can. You don't create an array of chessman objects, you create an array of pointers to chessman objects. Then chessman can be abstract (as it should be, since you should not be creating instances of chessman directly to begin with).
pawn class inherits chessman and I need to use move function of pawn when I write this
Polymorphism handles that for you. But in order to use an array of polymorphic objects, the array needs to hold pointers/references to objects that are stored elsewhere in memory, not hold the actual objects themselves.
In Java, it's easy since you can create arrays of abstract classes, but in C++ it is just confusing.
You do the exact same thing in C++. In Java, objects are reference types, so they are always referenced by pointer (the Java language simply hides that detail from you).
Try something like this:
class chessman
{
private:
virtual bool isValidMove(string final_pos) = 0;
public:
int i;
int j;
string name;
char color;
chessman(string aname, char acolor);
bool move(string final_pos);
};
chessman::chessman(string aname, char acolor)
: name(aname), color(acolor)
{
}
bool chessman::move(string final_pos)
{
// validate that final_pos is a valid position on the board...
// validate that final_pos is a valid position for the piece being moved...
if (!isValidMove(final_pos))
return false;
// move to the position...
return true;
}
class pawn : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
pawn(string pos, char color);
};
pawn::pawn(string pos, char color)
: chessman("pawn", color)
{
//...
}
bool pawn::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this pawn to move to...
return ...;
}
class rook : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
rook(string pos, char color);
};
rook::rook(string pos, char color)
: chessman("rook", color)
{
//...
}
bool rook::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this rook to move to...
return ...;
}
class knight : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
knight(string pos, char color);
};
knight::knight(string pos, char color)
: chessman("knight", color)
{
//...
}
bool knight::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this knight to move to...
return ...;
}
class bishop : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
bishop(string pos, char color);
};
bishop::bishop(string pos, char color)
: chessman("bishop", color)
{
//...
}
bool bishop::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this bishop to move to...
return ...;
}
class queen : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
queen(string pos, char color);
};
queen::queen(string pos, char color)
: chessman("queen", color)
{
//...
}
bool queen::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this queen to move to...
return ...;
}
class king : public chessman
{
private:
virtual bool isValidMove(string final_pos);
public:
king(string pos, char color);
};
king::king(string pos, char color)
: chessman("king", color)
{
//...
}
bool king::isValidMove(string final_pos)
{
// validate that final_pos is a valid position for this king to move to...
return ...;
}
Then you can do somthing like this:
chessman* white_pieces[16];
chessman* black_pieces[16];
for (int i = 0; i < 8; ++i)
{
white_pieces[i] = new pawn(...);
black_pieces[i] = new pawn(...);
}
for (int i = 8; i < 10; ++i)
{
white_pieces[i] = new rook(...);
black_pieces[i] = new rook(...);
}
for (int i = 10; i < 12; ++i)
{
white_pieces[i] = new knight(...);
black_pieces[i] = new knight(...);
}
for (int i = 12; i < 14; ++i)
{
white_pieces[i] = new bishop(...);
black_pieces[i] = new bishop(...);
}
white_pieces[14] = new queen(...);
black_pieces[14] = new queen(...);
white_pieces[15] = new king(...);
black_pieces[15] = new king(...);
And move them around as needed:
white_pieces[index]->move(pos);
...
black_pieces[index]->move(pos);
And of course, don't forget to cleanup when you are done:
for (int i = 0; i < 16; ++i)
{
delete white_pieces[i];
delete black_pieces[i];
}
To make the cleanup automatic, you can use an array of std::auto_ptr<chessman> objects. Or, in C++11 and later, a std::vector/std::array of std::unique_ptr<chessman> objects.
In C++ you would create a vector (or possibly array in C++11) of some sort of pointer (the pointer type would be dictated by the object ownership) to a chessman, and have chessman be abstract. It's just a slightly different way of thinking about things.
(Edited as the comments made a great point):
To make it select the proper move function, utilize the virtual mechanism in the base class. I would suggest to separate interface from implementation by not having public virtual functions. Instead, use a public non-virtual interface and a private or protected virtual implementation. You would use a private implementation which each child totally replaces the functionality while you would use protected when the child class needs to also invoke the parent functionality.

C++ Convert pointer from one derived class to another

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/

Storing member function pointers of derived classes in map

I am trying to implement a factory for two classes Circle, Square both of which inherits from Shape.
class Shape {
public:
virtual static
Shape * getInstance() = 0;
};
class Circle : public Shape {
public:
static const std::string type;
Shape * getInstance() {
return new Circle;
}
};
const std::string Circle::type = "Circle";
class Square : public Shape {
public:
static const std::string type;
Shape * getInstance() {
return new Square;
}
};
const std::string Square::type = "Square";
I want to now create a map with key as shape type (string) and value as a function pointer to getInstance() of the corresponding derived class. Is it possible?
Thanks,
Kiran
Okay I got the mistake.
1) shouldn't declare - virtual static Shape * getInstance() = 0; - in Shape class.
2) getInstance() should be static in all other classes.
Here is the complete implementation
class Shape {
public:
virtual
std::string getType() = 0;
};
class Circle : public Shape {
public:
static const std::string type;
Circle() {
}
std::string getType() {
return type;
}
static
Shape * getInstance() {
return new Circle;
}
};
const std::string Circle::type = "Circle";
class Square : public Shape {
public:
static const std::string type;
Square() {
}
std::string getType() {
return type;
}
static
Shape * getInstance() {
return new Square;
}
};
const std::string Square::type = "Square";
class Triangle : public Shape {
public:
static const std::string type;
Triangle() {
}
std::string getType() {
return type;
}
static
Shape * getInstance() {
return new Triangle;
}
};
const std::string Triangle::type = "Triangle";
typedef Shape * (*getShape)();
typedef std::map<std::string, getShape > factoryMap;
class ShapeFactory {
public:
static factoryMap shapes;
Shape * getInstance(const std::string & type){
factoryMap::iterator itr = shapes.find(type);
if (itr != shapes.end()){
return (*itr->second)();
}
return NULL;
}
};
factoryMap ShapeFactory::shapes;
class ShapeFactoryInitializer {
static ShapeFactoryInitializer si;
public:
ShapeFactoryInitializer() {
ShapeFactory::shapes[Circle::type] = &Circle::getInstance;
ShapeFactory::shapes[Square::type] = &Square::getInstance;
ShapeFactory::shapes[Triangle::type] = &Triangle::getInstance;
}
};
ShapeFactoryInitializer ShapeFactoryInitializer::si;
Although not much relevant to your question, but if you are interested in modern C++ design (factories, smart pointers, etc.), you may like to check this book:
http://www.amazon.co.uk/Modern-Design-Applied-Generic-Patterns/dp/0201704315/ref=sr_1_20?s=books&ie=UTF8&qid=1293359949&sr=1-20
It talk about factories, how to design them, etc.
PS: I am not the author of the book, nor I have been given any thing in return for posting this answer :-)
Change the last line of your code to ShapeFactoryInitializer ShapeFactoryInitializer::si;, then it will pass compilation.