How to check if another object is my superclass from a function in aneven higher superclass?

Discussion in 'C++' started by bart van deenen, Mar 3, 2009.

  1. Hi

    I have a pile of objects all derived from one baseclass, and I want to
    have a generic function that an object can use to see if another
    object is its superclass. Here's an example that does not work:

    #include <stdio.h>
    #include <typeinfo>

    class A {
    public:
    void check(A *other) {
    __typeof__(this) x = dynamic_cast<__typeof__(other)>(other);
    if ( x ) printf("ok\n");
    else printf("NULL\n");
    }
    };

    class B : public A { };
    class C: public B { };
    class D: public A { };

    int main()
    {
    D d;
    A a;
    C c;
    printf("c.check(&a)\n");
    c.check(&a);
    printf("c.check(&d)\n");
    c.check(&d);
    }

    g++ -frtti -Wall -o main main.cpp

    c.check(&a)
    ok
    c.check(&d)
    ok
    but C does not inherit from D!

    I now know more about the function of the __typeof__ operator, so I
    understand why it doesn't work. But how would you do this? Is there an
    elegant way?
     
    bart van deenen, Mar 3, 2009
    #1
    1. Advertising

  2. Re: How to check if another object is my superclass from a functionin an even higher superclass? (Qt solution)

    One solution I have is that fact that I'm using Qt QObject derived
    objects, so I can use the metaObject() information that is provided by
    the meta object precompiler. Like this:

    if ( this->inherits( other->metaObject()->className()) )
    ...

    which works perfectly well, but I just wonder if there is no more
    generic C++ solution for this.

    Bart
     
    bart van deenen, Mar 3, 2009
    #2
    1. Advertising

  3. bart van deenen

    Kai-Uwe Bux Guest

    Re: How to check if another object is my superclass from a function in an even higher superclass?

    bart van deenen wrote:

    > Hi
    >
    > I have a pile of objects all derived from one baseclass, and I want to
    > have a generic function that an object can use to see if another
    > object is its superclass.

    [snip: something using __typeof__]
    > I now know more about the function of the __typeof__ operator, so I
    > understand why it doesn't work.


    First, __typeof__ does not exists in standard C++. There is a typeof
    operator, though.

    > But how would you do this? Is there an elegant way?


    Well, for starters, there is the use of virtual functions:

    class Base {
    protected:

    virtual
    bool do_check ( Base * ptr ) {
    return ( true );
    }

    public:

    bool subclass ( Base * ptr ) {
    return do_check( ptr );
    }

    bool superclass ( Base * ptr ) {
    return ptr->do_check( this );
    }

    };

    class D1 : public Base {

    bool do_check ( Base * ptr ) {
    return ( dynamic_cast< D1* >( ptr ) );
    }

    };

    class D2 : public D1 {

    bool do_check ( Base * ptr ) {
    return ( dynamic_cast< D2* >( ptr ) );
    }

    };

    class D3 : public Base {

    bool do_check ( Base * ptr ) {
    return ( dynamic_cast< D3* >( ptr ) );
    }

    };


    #include <iostream>
    #include <iomanip>

    #define CHECK(expr) std::cout << #expr << " : " \
    << std::boolalpha << expr << "\n";

    int main ( void ) {
    Base b;
    D1 d1;
    D2 d2;
    D3 d3;
    CHECK( b.subclass( &b ) );
    CHECK( b.subclass( &d1 ) );
    CHECK( b.subclass( &d2 ) );
    CHECK( b.subclass( &d3 ) );
    CHECK( d1.subclass( &b ) );
    CHECK( d1.subclass( &d1 ) );
    CHECK( d1.subclass( &d2 ) );
    CHECK( d1.subclass( &d3 ) );
    CHECK( d2.subclass( &b ) );
    CHECK( d2.subclass( &d1 ) );
    CHECK( d2.subclass( &d2 ) );
    CHECK( d2.subclass( &d3 ) );
    CHECK( d3.subclass( &b ) );
    CHECK( d3.subclass( &d1 ) );
    CHECK( d3.subclass( &d2 ) );
    CHECK( d3.subclass( &d3 ) );

    CHECK( b.superclass( &b ) );
    CHECK( b.superclass( &d1 ) );
    CHECK( b.superclass( &d2 ) );
    CHECK( b.superclass( &d3 ) );
    CHECK( d1.superclass( &b ) );
    CHECK( d1.superclass( &d1 ) );
    CHECK( d1.superclass( &d2 ) );
    CHECK( d1.superclass( &d3 ) );
    CHECK( d2.superclass( &b ) );
    CHECK( d2.superclass( &d1 ) );
    CHECK( d2.superclass( &d2 ) );
    CHECK( d2.superclass( &d3 ) );
    CHECK( d3.superclass( &b ) );
    CHECK( d3.superclass( &d1 ) );
    CHECK( d3.superclass( &d2 ) );
    CHECK( d3.superclass( &d3 ) );
    }

    The next observation is that do_check() looks more or less alike in all
    derived classes. In that regard, it is like a clone() function. There is a
    recent thread about how to fold this code into a policy or at least make
    sure that each derived class implements the method.


    BTW: I don't know very much about object oriented programming, but from what
    I hear, the need for a function like superclass() or subclass() is a design
    smell. What is the underlying problem that you have to solve?


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Mar 3, 2009
    #3
  4. Re: How to check if another object is my superclass from a functionin an even higher superclass?

    On 3 mrt, 11:10, Kai-Uwe Bux <> wrote:
    > bart van deenen wrote:
    > > Hi

    >
    > > I have a pile of objects all derived from one baseclass, and I want to
    > > have a generic function that an object can use to see if another
    > > object is its superclass.

    >
    > [snip: something using __typeof__]
    >
    > > I now know more about the function of the __typeof__ operator, so I
    > > understand why it doesn't work.

    >
    > First, __typeof__ does not exists in standard C++. There is a typeof
    > operator, though.
    >
    > > But how would you do this? Is there an elegant way?

    >
    > Well, for starters, there is the use of virtual functions:
    >
    > class Base {
    > protected:
    >
    >   virtual
    >   bool do_check ( Base * ptr ) {
    >     return ( true );
    >   }
    >
    > public:
    >
    >   bool subclass ( Base * ptr ) {
    >     return do_check( ptr );
    >   }
    >
    >   bool superclass ( Base * ptr ) {
    >     return ptr->do_check( this );
    >   }
    >
    > };
    >
    > class D1 : public Base {
    >
    >   bool do_check ( Base * ptr ) {
    >     return ( dynamic_cast< D1* >( ptr ) );
    >   }
    >
    > };
    >
    > class D2 : public D1 {
    >
    >   bool do_check ( Base * ptr ) {
    >     return ( dynamic_cast< D2* >( ptr ) );
    >   }
    >
    > };
    >
    > class D3 : public Base {
    >
    >   bool do_check ( Base * ptr ) {
    >     return ( dynamic_cast< D3* >( ptr ) );
    >   }
    >
    > };
    >

    ....
    >
    > The next observation is that do_check() looks more or less alike in all
    > derived classes. In that regard, it is like a clone() function. There is a
    > recent thread about how to fold this code into a policy or at least make
    > sure that each derived class implements the method.
    >
    > BTW: I don't know very much about object oriented programming, but from what
    > I hear, the need for a function like superclass() or subclass() is a design
    > smell. What is the underlying problem that you have to solve?
    >

    Thanks for your answer

    My problem: I have a tree of displayable objects of different types.
    These object types have an class inheritance tree, and also have the
    capability to inherit attributes from their ancestor objects (in the
    tree, not in the class hierarchy). A bit like html and css.

    Now one of my nested objects might inherit an attribute (say 'color')
    and it will have to loop through its ancestors to find one that can
    provide it with the attribute 'color', but not all of its tree
    ancestors might be part of its own class inheritance path, so it won't
    even ask those if they have the attribute value available.

    So my reasoning is that by asking another tree object if its part of
    my class inheritance, is that if it says no, i don't have to ask it
    for the 'color' attribute.

    Hope this makes sense.
     
    bart van deenen, Mar 3, 2009
    #4
  5. Re: How to check if another object is my superclass from a function in an even higher superclass?

    bart van deenen <> writes:

    > On 3 mrt, 11:10, Kai-Uwe Bux <> wrote:
    >> bart van deenen wrote:
    >> > Hi

    >>
    >> > I have a pile of objects all derived from one baseclass, and I want to
    >> > have a generic function that an object can use to see if another
    >> > object is its superclass.

    >>
    >> [snip: something using __typeof__]
    >>
    >> > I now know more about the function of the __typeof__ operator, so I
    >> > understand why it doesn't work.

    >>
    >> First, __typeof__ does not exists in standard C++. There is a typeof
    >> operator, though.
    >>
    >> > But how would you do this? Is there an elegant way?

    >>
    >> Well, for starters, there is the use of virtual functions:
    >> [...]
    >> BTW: I don't know very much about object oriented programming, but from what
    >> I hear, the need for a function like superclass() or subclass() is a design
    >> smell.


    Not necessarily (in more dynamic programming languages these methods
    have their use). But indeed, when programming in C++, unless you want
    a dynamic programming style, it will be better to stick to virtual
    methods.

    >> What is the underlying problem that you have to solve?
    >>

    > Thanks for your answer
    >
    > My problem: I have a tree of displayable objects of different types.
    > These object types have an class inheritance tree, and also have the
    > capability to inherit attributes from their ancestor objects (in the
    > tree, not in the class hierarchy). A bit like html and css.
    >
    > Now one of my nested objects might inherit an attribute (say 'color')
    > and it will have to loop through its ancestors to find one that can
    > provide it with the attribute 'color', but not all of its tree
    > ancestors might be part of its own class inheritance path, so it won't
    > even ask those if they have the attribute value available.
    >
    > So my reasoning is that by asking another tree object if its part of
    > my class inheritance, is that if it says no, i don't have to ask it
    > for the 'color' attribute.
    >
    > Hope this makes sense.


    Do use virtual methods! All the objects that can belong to this tree
    shall be of a subclass of some abstract class that will publish the
    virtual methods needed.

    The default implementation of a method such as color() could be to
    return the parent's color, and then you don't have to write the loop
    explicitely.

    class TreeItem
    {
    protected:
    TreeItem* parent;
    public:
    static Color* defaultColor;

    TreeItem(TreeItem* anItem):parent(anItem){}

    virtual Color* color(){ return((parent==0)?defaultColor:parent->color()); }
    // ...
    };


    class DisplayableObject:public TreeItem
    {
    public:
    Color* color(){return(0);}
    };

    class Box:public DisplayableObject
    {
    // ...
    virtual Color* color(){
    Color* superColor=SUPERCLASS::color();
    return((superColor==0)?parent->color():superColor);
    }

    };


    --
    __Pascal Bourguignon__
     
    Pascal J. Bourguignon, Mar 3, 2009
    #5
  6. Re: How to check if another object is my superclass from a functionin an even higher superclass?

    On 3 mrt, 13:02, (Pascal J. Bourguignon) wrote:
    > bart van deenen <> writes:
    >
    >
    >
    > > On 3 mrt, 11:10, Kai-Uwe Bux <> wrote:
    > >> bart van deenen wrote:
    > >> > Hi

    >
    > >> > I have a pile of objects all derived from one baseclass, and I want to
    > >> > have a generic function that an object can use to see if another
    > >> > object is its superclass.

    >
    > >> [snip: something using __typeof__]

    >
    > >> > I now know more about the function of the __typeof__ operator, so I
    > >> > understand why it doesn't work.

    >
    > >> First, __typeof__ does not exists in standard C++. There is a typeof
    > >> operator, though.

    >
    > >> > But how would you do this? Is there an elegant way?

    >
    > >> Well, for starters, there is the use of virtual functions:
    > >> [...]
    > >> BTW: I don't know very much about object oriented programming, but from what
    > >> I hear, the need for a function like superclass() or subclass() is a design
    > >> smell.

    >
    > Not necessarily (in more dynamic programming languages these methods
    > have their use).  But indeed, when programming in C++, unless you want
    > a dynamic programming style, it will be better to  stick to virtual
    > methods.
    >
    >
    >
    > >> What is the underlying problem that you have to solve?

    >
    > > Thanks for your answer

    >
    > > My problem: I have a tree of displayable objects of different types.
    > > These object types have an class inheritance tree, and also have the
    > > capability to inherit attributes from their ancestor objects (in the
    > > tree, not in the class hierarchy). A bit like html and css.

    >
    > > Now one of my nested objects might inherit an attribute (say 'color')
    > > and it will have to loop through its ancestors to find one that can
    > > provide it with the attribute 'color', but not all of its tree
    > > ancestors might be part of its own class inheritance path, so it won't
    > > even ask those if they have the attribute value available.

    >
    > > So my reasoning is that by asking another tree object if its part of
    > > my class inheritance, is that if it says no, i don't have to ask it
    > > for the 'color' attribute.

    >
    > > Hope this makes sense.

    >
    > Do use virtual methods!  All the objects that can belong to this tree
    > shall be of a subclass of some abstract class that will publish the
    > virtual methods needed.  
    >
    > The default implementation of a method such as color() could be to
    > return the parent's color, and then you don't have to write the loop
    > explicitely.  
    >
    > class TreeItem
    > {
    > protected:
    >     TreeItem* parent;
    > public:
    >     static Color* defaultColor;
    >
    >     TreeItem(TreeItem* anItem):parent(anItem){}
    >
    >     virtual Color* color(){ return((parent==0)?defaultColor:parent->color()); }
    >     // ...
    >
    > };
    >
    > class DisplayableObject:public TreeItem
    > {
    > public:
    >     Color* color(){return(0);}
    >
    > };
    >
    > class Box:public DisplayableObject
    > {
    >     // ...
    >     virtual Color* color(){
    >         Color* superColor=SUPERCLASS::color();
    >         return((superColor==0)?parent->color():superColor);
    >    }
    >
    > };
    >
    > --
    > __Pascal Bourguignon__


    I think I like your approach, it will just mean a huge number of
    setters and getters all of them with that default behavior.

    What I really don't like about this approach is that for instance a
    property 'linewidth' which probably does not exist in half of the
    treeitem class types now has to have an accessor function in the
    toplevel superclass. That's an ugly contamination of the top
    superclass, but it's probably unavoidable. :-(

    Thanks for thinking along.

    Bart

    P.S. I've been programming a lot in Python recently, and that really
    is much nicer for this kind of thing :)
     
    bart van deenen, Mar 3, 2009
    #6
  7. Re: How to check if another object is my superclass from a functionin an even higher superclass?

    On 3 mrt, 13:02, (Pascal J. Bourguignon) wrote:
    > bart van deenen <> writes:
    >
    >
    >
    > > On 3 mrt, 11:10, Kai-Uwe Bux <> wrote:
    > >> bart van deenen wrote:
    > >> > Hi

    >
    > >> > I have a pile of objects all derived from one baseclass, and I want to
    > >> > have a generic function that an object can use to see if another
    > >> > object is its superclass.

    >
    > >> [snip: something using __typeof__]

    >
    > >> > I now know more about the function of the __typeof__ operator, so I
    > >> > understand why it doesn't work.

    >
    > >> First, __typeof__ does not exists in standard C++. There is a typeof
    > >> operator, though.

    >
    > >> > But how would you do this? Is there an elegant way?

    >
    > >> Well, for starters, there is the use of virtual functions:
    > >> [...]
    > >> BTW: I don't know very much about object oriented programming, but from what
    > >> I hear, the need for a function like superclass() or subclass() is a design
    > >> smell.

    >
    > Not necessarily (in more dynamic programming languages these methods
    > have their use).  But indeed, when programming in C++, unless you want
    > a dynamic programming style, it will be better to  stick to virtual
    > methods.
    >
    >
    >
    > >> What is the underlying problem that you have to solve?

    >
    > > Thanks for your answer

    >
    > > My problem: I have a tree of displayable objects of different types.
    > > These object types have an class inheritance tree, and also have the
    > > capability to inherit attributes from their ancestor objects (in the
    > > tree, not in the class hierarchy). A bit like html and css.

    >
    > > Now one of my nested objects might inherit an attribute (say 'color')
    > > and it will have to loop through its ancestors to find one that can
    > > provide it with the attribute 'color', but not all of its tree
    > > ancestors might be part of its own class inheritance path, so it won't
    > > even ask those if they have the attribute value available.

    >
    > > So my reasoning is that by asking another tree object if its part of
    > > my class inheritance, is that if it says no, i don't have to ask it
    > > for the 'color' attribute.

    >
    > > Hope this makes sense.

    >
    > Do use virtual methods!  All the objects that can belong to this tree
    > shall be of a subclass of some abstract class that will publish the
    > virtual methods needed.  
    >
    > The default implementation of a method such as color() could be to
    > return the parent's color, and then you don't have to write the loop
    > explicitely.  
    >
    > class TreeItem
    > {
    > protected:
    >     TreeItem* parent;
    > public:
    >     static Color* defaultColor;
    >
    >     TreeItem(TreeItem* anItem):parent(anItem){}
    >
    >     virtual Color* color(){ return((parent==0)?defaultColor:parent->color()); }
    >     // ...
    >
    > };
    >
    > class DisplayableObject:public TreeItem
    > {
    > public:
    >     Color* color(){return(0);}
    >
    > };
    >
    > class Box:public DisplayableObject
    > {
    >     // ...
    >     virtual Color* color(){
    >         Color* superColor=SUPERCLASS::color();
    >         return((superColor==0)?parent->color():superColor);
    >    }
    >
    > };
    >
    > --

    Hi Pascal

    one more thing, what I dislike about this approach is that a now have
    a global namespace for attribute names via the getters and setters in
    the top superclass. In my approach, I can have subclasses of different
    types use the same named attribute 'color' for instance, without them
    biting each other. I wonder if that's even a disadvantage though.

    The problem is that the whole tree structure is completely dynamic,
    driven from google protocol buffer encoded data, that already has
    attribute names inside it, and I'm pretty sure I'll get attribute
    collisions there.

    I'll have to play with it a bit.

    Thanks

    Bart
     
    bart van deenen, Mar 3, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt
    Replies:
    3
    Views:
    15,592
    Tony Morris
    Apr 26, 2004
  2. Replies:
    5
    Views:
    358
    Patricia Shanahan
    Oct 7, 2006
  3. Evan Klitzke
    Replies:
    0
    Views:
    388
    Evan Klitzke
    Aug 2, 2007
  4. Michael Preminger
    Replies:
    5
    Views:
    414
    Roedy Green
    Mar 18, 2010
  5. Siratinee Sukachai
    Replies:
    1
    Views:
    147
    7stud --
    Apr 22, 2011
Loading...

Share This Page