LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C++ list of mixed classes (https://www.linuxquestions.org/questions/programming-9/c-list-of-mixed-classes-420670/)

martinrp 03-01-2006 12:24 PM

C++ list of mixed classes
 
Hello

I have some classes like so:

class node
{
//data and functions
}

class specific : public node
{
aFunction();
}

class specific2 : public node
{
anotherFunction();
}


and I have a list of pointers to objects of class node:
list<node *> node_list;

but all these objects are in fact a mixture of class specific and specific2, as they both inherit from class node.

I wish to iterate through my list and call aFunction() or anotherFunction() based on what type my node actually is.

How do I:
tell what type my node is?
subsequently call the correct function?

Thanks

Martin

dmail 03-01-2006 02:31 PM

Well do you need to know what type it is? do you need to call different functions?
As they both inhert from node you could use polymorphism, if do don't know what this is just do a quick google.
You could also try casting down(ie from node to specific or specific2. checking the value) but this is normal evidence of bad design.

spooon 03-01-2006 03:23 PM

Preferably you can rename anotherFunction() to aFunction() also and make a virtual aFunction() in node, so that you can call aFunction() for any "node" and it will call the right one and then you don't have to tell which type it is.

xhi 03-01-2006 03:26 PM

here is an example of what dmail was saying..
Code:

#include <iostream>
using namespace std;

class Foo {
    public:
        virtual void who(){ cout << "in Foo" << endl; }
};

class FooBar : public Foo {
    public:
        virtual void who(){ cout << "in FooBar" << endl; }
};

class FooBaz : public Foo {
    public:
        virtual void who(){ cout << "in FooBaz" << endl; }
};

void test(Foo& f){ f.who(); }

int main(){
    Foo f;
    FooBar fbar;
    FooBaz fbaz;
    test(f);
    test(fbar);
    test(fbaz);
    return 0;
}

output is:
in Foo
in FooBar
in FooBaz

notice how the test function just requires a Foo, and then from the base Foo it finds the correct function for the object that it was passed..

isnt c++ great. :)

and as was suggested read up on polymorphism..

ta0kira 03-01-2006 04:33 PM

Quote:

Originally Posted by xhi
here is an example of what dmail was saying..

Don't forget a virtual destructor for Foo (even if not using "= 0;"); you can get into big trouble otherwise!
ta0kira

xhi 03-01-2006 04:58 PM

Quote:

Originally Posted by ta0kira
Don't forget a virtual destructor for Foo (even if not using "= 0;"); you can get into big trouble otherwise!
ta0kira

very true.. nice catch!

aluser 03-02-2006 08:25 PM

To literally do what martinrp asked, you can use dynamic_cast -- google for it. But the others are right; it looks like you should use polymorphism instead.

ta0kira 03-03-2006 12:26 PM

Quote:

Originally Posted by aluser
To literally do what martinrp asked, you can use dynamic_cast -- google for it.

I think static_cast is much safer; in my experience, dynamic_cast returns NULL unpredictably, however I've never had a problem with static_cast. The big difference is that, even though dynamic_cast generally has the same compilation rules, it's left with the option to "veto" a cast at run-time.
ta0kira

PS dynamic_cast is also dependent on RTTI, which increases your overhead...

dmail 03-03-2006 01:37 PM

Quote:

Originally Posted by ta0kira
I think static_cast is much safer; in my experience, dynamic_cast returns NULL unpredictably, however I've never had a problem with static_cast. The big difference is that, even though dynamic_cast generally has the same compilation rules, it's left with the option to "veto" a cast at run-time.
ta0kira

PS dynamic_cast is also dependent on RTTI, which increases your overhead...

Like I said in the earlier post
Quote:

You could also try casting down(ie from node to specific or specific2. checking the value) but this is normal evidence of bad design.
As far as I am aware you must use dynamic cast to cast down. When you down cast you should always check the pointer after casting, if its null then it was an invalid cast. It's considered bad design due to the overhead and there are better ways.

<edit>
correction
Quote:

You can use static_cast to cast "down" a hierarchy (from a base to a derived pointer or reference), but the conversion is not checked; the result might not be usable. A static_cast cannot be used to cast down from a virtual base class.
http://docs.sun.com/source/806-3571/Cast.html

aluser 03-03-2006 02:32 PM

ta0kira: the OP said he didn't know what types the node*s were pointing to. dynamic_cast can figure that out; it returns null if you guess the wrong one. static_cast can't figure that out; it only knows what you tell it.

ta0kira 03-04-2006 05:18 PM

Quote:

Originally Posted by aluser
ta0kira: the OP said he didn't know what types the node*s were pointing to. dynamic_cast can figure that out; it returns null if you guess the wrong one. static_cast can't figure that out; it only knows what you tell it.

You are correct, except that gcc doesn't like to compile reverse casts using dynamic_cast.
Quote:

Originally Posted by dmail
As far as I am aware you must use dynamic cast to cast down.

You can reverse cast with static_cast, but it doesn't check for run-time validity.

I suppose I have just never been a fan of dynamic_cast; I think it's one of those things like reinterpret_cast that should be avoided whenever possible.

Here is the scenario I picture; you have a heterogenous list, and every operation on an element starts by seeing the element as the base class. At a certain point, the operation will decide which derived class the element is, and at that point will cast it and perform an operation on it. This can all be easily avoided by creating an extra virtual function, thereby avoiding all casts, and also allowing the addition of other derived classes without adding additional casts.
ta0kira

ta0kira 03-13-2006 12:00 PM

Quote:

Originally Posted by ta0kira
I suppose I have just never been a fan of dynamic_cast; I think it's one of those things like reinterpret_cast that should be avoided whenever possible.

Well, I actually found an excellent reason for dynamic_cast yesterday (never thought I would): you would need it if you had a class with abstract arithmetic operators...
ta0kira


All times are GMT -5. The time now is 03:02 AM.