# C++ templates, polymorphism and inheritance

This topic is 2505 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

[color=#000000][font=verdana, arial, helvetica, sans-serif]

### I've tried this with both GridTiles and classes that inherit from GridTile and it seems to work ok. Am I about right in my approach?[/font]

##### Share on other sites

I want to write the Grid class so that the 2D vector can store GridTile tiles or any type that inherits from GridTile.

 vector< vector< GridTile* > > grid; 
Better to use a smart pointer though.

##### Share on other sites

[quote name='altich88' timestamp='1328701718' post='4910867']
I want to write the Grid class so that the 2D vector can store GridTile tiles or any type that inherits from GridTile.

 vector< vector< GridTile* > > grid; 
Better to use a smart pointer though.
[/quote]

Thanks for your reply. Why is it better to use a pointer here?

(I'm coming to C++ from Java so please excuse my ignorance with pointers - I've used a few basic examples but am still learning on when best to use them!)

##### Share on other sites

[quote name='Rene Z' timestamp='1328704884' post='4910875']
[quote name='altich88' timestamp='1328701718' post='4910867']
I want to write the Grid class so that the 2D vector can store GridTile tiles or any type that inherits from GridTile.

 vector< vector< GridTile* > > grid; 
Better to use a smart pointer though.
[/quote]

Thanks for your reply. Why is it better to use a pointer here?

(I'm coming to C++ from Java so please excuse my ignorance with pointers - I've used a few basic examples but am still learning on when best to use them!)
[/quote]

Templates are used for generic programming like lists in which you want to be able to store any datatype. And you only define the storage container and it's operations but not the data type.
What you want however is polymorifsme, and to store classes that derive from the same type but are in a hetreogeneous collection, you need a pointer to the base class as the data type of your list.

You could use a void* pointer but thats not very nice and you lose all functionality to loop over the list and call commenly defined functions (defined in the base class or interface) on it.

##### Share on other sites

Thanks for your reply. Why is it better to use a pointer here?

The SomeType* means a pointer to SomeType, but that's a raw pointer. Raw pointers can easily cause problems in large codebases like dangling pointers, memory leaks, heap corruption just to name a few.

A smart pointer is a small class or struct that manages the data it's pointing to. Basically, this means the pointed-to data will automatically be deleted as soon as there's no longer a pointer pointing to it, and no sooner than that. Most high quality code bases will almost exclusively use smart pointers.

As NightCreature said, if you want to use polymorphism you must use pointers or references. If you want to understand why, look up the 'slicing problem'. The following answer on StackOverflow explains nicely:
http://stackoverflow...lem-in-c#274636

##### Share on other sites

...

...

Thanks for the links, very useful. So it seems polymorphism is the way to go rather than templates. Does this mean I will have to cast to the derived class like so to gain access to the derived class members etc?

I've had a play with the following which seems to work.

 class Base { public: int a; Base() { a = 1; } }; class Deriv : public Base { public: int b; Deriv() : Base() { b = 2; } }; Base* pBase; Deriv* pDeriv; Deriv deriv1; pDeriv = &deriv1; pDeriv->a = 100; pDeriv->b = 200; pBase = pDeriv; cout << ((Deriv*)(pBase))->b << endl; // works 

Firstly would this be the correct approach?

Secondly, if so, let's say you had an array of base class pointers, some of which pointed to objects of the base class type, but some pointed to objects of derived class type. In this situation how would you know what to cast to? Do you have to have some kind of ID field defined for each type of object? e.g.

 #define BASE_ID 1 #define DERIV_ID 2 int type = BASE_ID; for example?

Many thanks for your help so far, much appreciated.

##### Share on other sites
It depends what your goal is.

If you want to hold both GridTile and UITile in the same Grid instance, then you have to use base class pointers like everyone has been saying (there are other non-standard "hacks" you could do, but are tricky and subject to a lot of caveats, so I won't go into that).

However, if just one type of tile will be stored per Grid instance, then you can indeed use templates. The pros of templates are that you'll save memory (you only have to store tiles, not tiles *and* pointers), you'll avoid dynamic allocation and manual memory management (pooled allocation and smart pointers help when these things can't be avoided, but its always better to not have a problem at all, than to have to fix it), and that your Tiles will be in contiguous memory and so won't thrash your CPU cache (pooled allocations can help here too, but again, the simplest solution is to avoid the problem in the first place.) The cons of Templates are that both Grid types (one for GridTiles, the other for UITiles) are more or less identical, but completely incompatible -- you won't be able to copy data directly from one to the other, you won't be able to write a function which can take both types as parameters (but you can write a template function, or overload on both types), and you end up with two copies of the code for each (in practice, the compiler will minimize the amount of redundant code, but there is almost always some); complex templates can also take a while to compile, but this case is simple.

All that being said, the bigger question is how different a UITile actually is from a GridTile. Its possible, if not likely, that by dividing the duties of these classes differently, that you might be able to avoid this problem altogether. It's very common to reach for inheritance almost as a reflex, but this can lead to deep hierarchies and the diamond inheritance problem if you're not careful. Experienced developers using the OOP paradigm know that a limited use of inheritance is typically a sign of good code, and that you can get there by dividing responsibilities clearly and keeping classes focused on a single task. You shouldn't avoid inheritance by creating your own version of it, mind you -- use the real thing when its the right solution -- just don't start with the assumption that its always the right solution.

If you share how your tile types are different, we might be able to come up with an altogether different solution.

##### Share on other sites

If you want to hold both GridTile and UITile in the same Grid instance, then you have to use base class pointers like everyone has been saying (there are other non-standard "hacks" you could do, but are tricky and subject to a lot of caveats, so I won't go into that).

### Thanks for your help so far, very useful stuff and it's much appreciated.[/font]

##### Share on other sites

[quote name='Ravyne' timestamp='1328715503' post='4910923']
If you want to hold both GridTile and UITile in the same Grid instance, then you have to use base class pointers like everyone has been saying (there are other non-standard "hacks" you could do, but are tricky and subject to a lot of caveats, so I won't go into that).

### Thanks for your help so far, very useful stuff and it's much appreciated.[/font] [/quote] There is and there isn't when you turn RTTI on the runtime can tell you which type it is, without it there is no way to find out. But you usually don't care about it because the base class defines the public interface for what you want to do. You can override the functions in a derived version and in those you can actually access your derived members as well.

##### Share on other sites
In this particular case it sounds like you're optimizing something that doesn't need to be optimized -- since any reasonable UI is built on parent-child relationships, its already got a good way to minimize the work that goes into mouse selection. When you consider the overhead of moving controls around the grid as a window is dragged around, this approach is costing you more than its worth, IMHO (certainly in terms of code-complexity, if not performance). Furthermore, a click on a unique control happens perhaps every few seconds, so its hardly something that needs to be optimized *at all*. I also worry, but can't confirm based on information given, that this indicates tight and unnecessary coupling between the UI and other program logic.

There are better ways to optimize this. For starters:

1. Each time you click (or mouse-over), store a pointer/handle to that control. The next time you click (or move the mouse) check that item first (and its children, if it has any) before doing anything else. If you find a match this way, you're done (but be careful to reset if a window pops over that control). This will probably catch 70% of clicks, and 99% of mouse-over-like changes -- and its dead-simple to implement.
2. Instead of this grid approach, do a recursive search starting with the main window (assume a window is rectangular, and do finer detection as a second step only if the rect matches), descending into each child that matches, and repeat for its children until no child is a better match. Wherever you end is the control that is under the cursor. This, combined with the first suggestion, will already be very highly optimal.
3. If (and only if) performance is still unacceptable (maybe if this were applied to many small units in an RTS with hundreds+ units on screen) then you can also sort the controls for quicker detection -- for each child control, add to a list that controls y coordinate (relative to its parent), its height, and a pointer to the child control (or just do the list of child controls this way). This list should be sorted by the y element. You then iterate over the list and add controls where mouse.y >= list[n].y and mouse.y < list[n].y + list[n].height, and early-out as soon as mouse.y > list[n].y. Now do the same using the x/width elements against the list of candidates (not the list of all controls). If your system allows multiple collisions to occur (such as due to overlap or transparency, choose the control with the nearest z element). I've described this as a list for simplicity, but better still would be to do this using a binary search tree.

You were right to think that partitioning things in a grid can help by reducing the number of items that need to be checked, but where you missed out was not exploiting the natural parent-child relationship here. Grids or other spacial partitioning techniques (BVHs in general, like quadtrees or octrees) are more suitable when a great number of entities (usually moving) occupy a single, large parent space -- for example, its common to split up a 2-D or 3-D gameworld using grids/quadtrees or octtrees, respectively.

1. 1
2. 2
Rutin
19
3. 3
khawk
18
4. 4
5. 5
A4L
11

• 12
• 16
• 26
• 10
• 44
• ### Forum Statistics

• Total Topics
633768
• Total Posts
3013748
×