Testing for inheritance

Started by
13 comments, last by sipickles 16 years, 4 months ago
Hi, Can anyone remind me of the method, in C++, to test if a derived object is derived from a particular base object? It is trivial in Python. Eg:

class BaseObject
{
..
};

class DerivedObject: public BaseObject 
{
..
}

DerivedObject d;

if ( d ......is derived from BaseObject........ )
 print "d is derived from BaseObject" 
else
 print "Its not"


thanks Si
Advertisement
If you absolutely must do so, you can use dynamic_cast to cast to a base pointer type at runtime, or something like boost::type_traits::is_base_of at compile time. However, in general, it's a better idea just not to lose that kind of type information in the first place.
You would use a dynamic_cast and check for null.

Generally speaking, when you need to start casting to subtypes you have an LSP violation.

In your example, BaseObject should have a virtual function called print() which is implemented in DerivedObject. Then you can simply call print() on the BaseObject pointer and get the correct behaviour.

If your design doesn't allow this, then your DerivedObject - BaseObject relationship probably doesn't satisfy the is-a relationship, and you should look at alternatives like aggregation/composition or private inheritance.
[size="1"]Try GardenMind by Inspirado Games !
All feedback welcome.
[s]
[/s]

[size="1"]Twitter: [twitter]Owen_Inspirado[/twitter]
Facebook: Owen Wiggins

[size="1"]Google+: Owen Wiggins

And if you're using a dynamic_cast then make sure you've got RTTI turned on when compiling otherwise you'll just get a mess. [grin]

So designs which use MI to assign properties are mistaken. Eg:

class Clickable {};

class Dragable {};


class ClickableDragableThing : public Clickable, public Dragable {}

ClickableDragableThing thing;

if ( thing == dragable() )
StartDrag();


Thats not real c++ code btw ;)


Yeah, dynamic_cast is what you want. I thought RTTI was fairly standard, which compiler doesn't enable that by default?

I sense the anti-dynamic_castness is quite big in this thread. However, while I wouldn't advice to use it always, I find it can be very nice in some cases, while having code that is easily maintainable even in large projects on which lots of people work.

E.g. if you have some database of items and you want to get items of a certain type: go over all items, dynamic cast to check if it's the type you want, if yes, add it to the result vector.

Multiple inheritence can also give designs that are perfectly understandable and maintainable, and can avoid code duplication, and in combination with dynamic casts you get a very nice toolbox.

C++ is not Java :)

Why would those things be bad?
I like the boost is_base_of idea. It fits my thinking, but maybe I've been working in Python world for too long where programming is actually logical!

Coming back to C++ is like detaching part of my brain and plugging in a PCB :-)

MI seems so powerful to me, yet so hated. Not sure I get why (yet!)
C++ is statically typed, so the only time you can have a derived object and not already know its base classes from its class is if you're trying to do a cast to a "cousin" or if you're doing template programming.

A cousin would be something like this:
class Base1{};class Base2{};class Derived : public Base1, public Base2{};Base1 *b1 = new Derived();Base2 *b2 = dynamic_cast<*Base2>(b1);if (b2)  cout << "b1 points to a class derived from base2";else  cout << "b1 does not point to a class derived from Base2";


With templates, you can use partial specialization.

Dynamic casts are discouraged because the result is often difficult to maintain, as logic dealing with different classes gets distributed throughout the code, instead of being encapsulated within the class definitions.

This is true in python as well, where the idiom is to assume the object supports the operations you are performing on it. For example, any function that works on "file-like objects" will work on any object that implements the same methods as files. If the functions checked to make sure the objects were actually files, then the code wouldn't work on non-file objects, but this needlessly reduces the usefulness of the code.
The feeling i get is that MI is treated with caution because inheriting from anything but fairly trivial multiple base classes quickly becomes quite a convoluted mess thats very hard to maintain. I'd have to agree with this.

As to your original question - the question itself leads me to believe you might want to rethink the way you structure your code. I don't believe inheritance (or at least the part of inheritance your using) was designed to give the information your trying to wrestle out of it - It is more to change the behaviour of an object without changing the interface.

To give you a pseudocode example, I have written a gui system where i have a base Window class. It has several virtual functions including :OnDrag(int iX, int iY), and :OnClick(int iX, int iY); These virtual functions are defined as doing nothing in the base class, and then i can derive a DraggableWindow from this window class, and all i need to do is implement these functions for draggable objects, and also (if needed) the click function.

Alex
Ok, I admit defeat, since I 've not heard one voice supporting MI. I concur that my structure stretches the bounds of encapsulation, but my MI structure is all based around one _type_ of object.

In reality, I am dealing with game objects, where I hoped to make several base classes which all objects derive from in various combinations. Each base class assigns an attribute like:

Selectable
Intelligent
Mobile
Container
etc

So I gather I should look at other approaches. By this we mean nested classes right?

This topic is closed to new replies.

Advertisement