getting child class pointer via dynamic_cast

Hi,

I've got a question about dynamic_cast<child*> (parent).

I have a parent class "window" with different members like "width, height, xpos, ypos etc.".
No I have a child class which inherits "windows". This child class additionally has members like "buttons, textedits, checkboxes etc.".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  class window
  {
    public:
      int xpos, ypos, width, height;

      window();
  };

  class window_child : public window
  {
    Button* button;
    TextEdit* textedit;
    CheckBox* checkbox;

    window_child(*parent = 0);
  };


In my cpp file, I have functions that return a pointer to window (parent class), although the class is a window_child object, example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(int argc, char** args)
{
  Table* table;
  window_child* cell_window;
  table->setCellWindow(cell_window);    // it is definitly an instance of window_child, that is placed into the table cells
/* .... */
  return 0;
}

  window* getCellWindow()
  {
    window* cell_window = getCellWindow();
    return cell_window;
  }


My problem is now, that I call this function to get pointers to instances of window_child out of a table. The problem is, that then, I have pointers to a basic class "window", so I can't use the members "button, textedit, checkbox etc."...

Now my two questions:
1. Is it the right way to use dynamic_cast in this case? Or are there other ways to solve a problem like this?

2. In case of it is possible to get a window_child instance by using dynamic_cast (or any other method), how can this work? I don't understand it.. How is it possible to get contents(members of child classes) out of a parent class which doesn't possess them? What happens while compiling that source? How can compiler add these members and from where?

Thank's for your support!

Hi,

Some things that might help:

A pointer or reference to a derived class is a valid pointer to a base class. So one can have a function that expects a pointer to window but one sends it a pointer to window_child. This is a very powerful and useful concept, because it cuts down on the number functions one needs to write.

Edit: And it is especially useful with virtual functions.

Derived classes inherit members from their base class (public or protected) , so a pointer to window_child should have access to the base class members in this case.

Having said that, protected member variables area bad idea: keep them all private, and provide accessor functions where appropriate. The pointer to the base class should still be able to use these.

I have heard that if one needs to use a dynamic_cast, then there is probably a better way.

Also investigate the use of initialiser lists in constructors. Edit: Base class constructors can still (& need to) be called from these.

The compiler maintains tables of pointers, so that given a pointer to a derived class, it can "navigate" it's way up the inheritance tree, to find whatever it needs - base class constructors or a virtual functions higher up the tree say.

Hope all is well :+)
Last edited on
A pointer or reference to a derived class is a valid pointer to a base class

Ok, I'm not sure whether I understood the principle or not.
When you say, a pointer to a window_child is also a pointer to window base class, then I think, in stack/heap it has to look like this:
1
2
3
4
5
6
7
|0x0000|base class start / child class start
|0x0004|base class member / child class member
|0x0008|base class member / child class member
|0x0016|base class member / child class member
|0x0020|child class member
|0x0024|child class member
|0x0028|child class member

Pointer points to 0x0000 and the last three members are added by defining child class and are no valid members of parent class. So when I use dynamic_cast, I only tell the compiler that the new pointer is a type window_child pointer --> bigger stack/heap --> access to the last three members...
is it like this or am I still on the wrong way??
In my C++ book, I read that instead of dynamic_cast I could also access window_child members by using something like this:
((window_child*)window_object)->child_member
This would underline my imagination about how compiler handles the different pointer access...

Right or wrong imagination? ^^
Last edited on
Hi,

Ok, I'm not sure whether I understood the principle or not.


This part ...

TheIdeasMan wrote:
The compiler maintains tables of pointers, so that given a pointer to a derived class, it can "navigate" it's way up the inheritance tree, to find whatever it needs - base class constructors or a virtual functions higher up the tree say.


So when a derived class constructor calls a base class constructor in it's initialiser list, the compiler looks at it's internal table of pointers (or references) to find out what the parent class is. If it is the same as what was specified in the derived constructor, it calls that base class constructor. If not, it looks to see if there is another parent class, and so on until it finds one, otherwise it is a compiler error.

The same thing happens with virtual functions.

If I understand you correctly, you are talking about accessing a derived class from a base class.

If so, this seems backwards to me: If you have a base class object, there is no derived class as part of it.

Here is a description example of what I am saying:

Imagine you have a CPie class, and there is a pure virtual function called MakePie has parameters for CPastry, and various type s of ingredients such as vegetables, meat, fruit, fish etc. All these things exist as classes under the base classes CIngredient and CPastry

Now, one could have this:

 
virtual void MakePie (CPastry &Pastry, CIngredient &Ingredient1, CIngredient &Ingredient2);


But this means that fish, fruit & meat could all mixed together which may not be want people want ! So it would probably more likely look something like this:

1
2
3
virtual void MakePie (CPastry &Pastry, CFruit &Ingredient1, CFruit &Ingredient2) ;
virtual void MakePie (CPastry &Pastry, CMeat &Ingredient1, CVege &Ingredient2) ;
virtual void MakePie (CPastry &Pastry, CFish &Ingredient1, CVege &Ingredient2) ;


So now to call the function:

1
2
3
4
5
6
7
CDessertPie MyPie();

CSweetPastry DessertPastry();
CApricot MyApricot();
CApple MyApple();

MyPie.MakePie (DessertPastry, MyApricot, MyApple);


The point with this whole thing is that the function is defined high up in the inheritance tree, but the compiler does the right thing, even when the objects are well down the tree. Also, we only have 3 functions, but we might have dozens of ingredients.

Does this clear up how it works?
Last edited on
Hi again,

first of all, thank you really much for that great support! I'm really happy about that!

Does this clear up how it works?

Well, I still don't really know how compiler realizes this in particular, but when I heard you right, the basic point is that compiler has a table of pointers which point to the base class and all it's child classes. So compiler starts with base class and then, searches downwards by reference to the table of pointers till it finds the right class with the needed members... right?
What I don't really understand is why I can do it the one way without any casts (creating an object of child class and treating it as base class object) but the other way (creating an object of base class and treating it as child class object) compiler throws an error, unless I don't cast it or call it with child pointer: ((child*)base_object)->member).
Why doesn't compiler manage this for me and automatically searches for those members in child classes?
hi

So compiler starts with base class and then, searches downwards by reference to the table of pointers till it finds the right class with the needed members... right?


TheIdeasMan wrote:
If I understand you correctly, you are talking about accessing a derived class from a base class.
If so, this seems backwards to me: If you have a base class object, there is no derived class as part of it.


With the Pie example, if you create a base class pie, you can't cast it to derived class pie (MyPie), because MyPie doesn't exist - hence you compile error. With the inheritance tree, it is usually always possible to go up the tree logically (classes usually have one parent - but not always); but it is not logically possible to go down - which derived class to choose from several, unless there is more info. When you cast that is where the extra info come from - you are providing the class to cast to.

Anyway, I said at the start - you shouldn't need to cast.
Topic archived. No new replies allowed.