Dynamic cast

Please excuse this Long example, but I am not sure,
which parts are relevant.

My question is:
Is the dynamic type cast in the following example correct?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class GeometricalObject : public ML::Object{
  private:
    Point position;
  public:
    GeometricalObject(Point p) : position(p) {..} //ctor?
};

class Rectangle : GeometricalObject {
  private:
    double width, heigth;
  public:
    Rectangle(Point p, double w, double h):
      GeometricalObject(p), width(w), heigth(h) {...}
}   

class Circle : GeometricalObject {
  private:
    double radius;
  public:
    Circle(Point p, double r) : GeometricalObject(p), radius(r) {...}
}

// Searched: Implementation of TotalArea(const Collection* geoObjects)

double GeometricalObject::TotalArea(const Collection* geoObjects)
{
  double ret = 0;
  Iterator *it = geoObjects->NewIterator(); // from ML::Collection
  Object *o = dynamic_cast<GeometricalObject*>(it->Next()); 
                //dynamic_cast<target-type> (Source-expr): 
  while (o != nullptr) {
    ret += o->GetArea();
    o = it->Next();
  }
  delete it;
  return ret;
}

//GeometricalObject.h - definition
public:
  virtual double GetArea() = 0 const;

//GeometricalObject.cpp - implementation

public:
  double Rectangle::GetArea() const { return width * height;}
  double Circle::GetArea() const { return radius * radius * 3.1415; }
  
Last edited on
Object* o = dynamic_cast<GeometricalObject*>(it->Next());
you're casting to Object, so it should be:
Object* o = dynamic_cast<Object*>(it->Next());
This tries to convert the pointer returned by it->Next() to a pointer of type Object* if *(it->Next()) is of type Object or else derived directly or indirectly from type Object (which seems to be true in your case).
Otherwise the expression evaluates to the nullpointer. So you could also replace line 31 with:
1
2
3
 if(o)
//or
if(o != nullptr) 


Thanks for the cast-info, that helped a lot.
By the way: I would like to Change line 31, because I want to read all objects of my Collection, isnĀ“t it?
... want to read all objects of my Collection ...

what you need then is to range-loop or iterate through the Collection object:
1
2
3
4
5
6
7
8
9
10
11
12
13
//range-loops
for (auto& elem : *geoObjects)
//geoObjects is a pointer to Collection, so dereferencing it gives the Collection object
{
	
	//...now elem gives access to each object within the Collection object
}
//(const) iterator
for (auto itr = (*geoObjects).cbegin(); itr != (*geoObjects).cend(); ++itr)
//assuming cbegin(), cend() etc are defined for Collection
{
	//...now (*itr) fulfills the role of elem above 
}

Another think you might wish to consider is to replace the C-style/raw pointers you're using currently with smart pointers:
https://msdn.microsoft.com/en-us/library/hh279674.aspx
1
2
3
4
5
6
7
8
9
10
11
//Assume (it->Next()) returns a raw-pointer to GeometricalObject
std::unique_ptr<GeometricalObject> o_GeoObj = it->Next()//move, not copy, assignment;
std::unique_ptr<Object> o (dynamic_cast<Object*>(o_GeoObj.get()));// cast the embedded raw pointer
if(o)
{
	o_GeoObj.release();//release object ownership transferred to o;
	//... continue as before
}
	//delete it; 
/* may be required if NewIterator() returns raw pointer created with new operator 
but if that is replaced also replaced with smart pointers then delete it not required */
Last edited on
Hi,

IMO you shouldn't need any casting, that is why I mentioned polymorphism.

Tutorial wrote:
Pointers to base class
One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.


Last edited on
from above:
tries to convert the pointer returned by it->Next() to a pointer of type Object* if *(it->Next()) is of type Object or else derived directly or indirectly from type Object (which seems to be true in your case).

... this has already been covered and moved on
Topic archived. No new replies allowed.