CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Inheritance and Implementation hiding..

    Hello Guys,

    I have to implement a class BASE which is abstarct and has a function called isEqual which ofcourse checks for equality..

    Now isEqual has to be pure virtual.

    Now bunch of derived classes deriving from base each having own implementation of isEqual method.

    Code:
    class BASE
    {
        bool isEqual(BASE* ptr);
    }
     
    Derived: public BASE
    {
       bool isEqual(BASE* ptr);
       {  
             //Here I have to do a dynamic cast which I dont want to do
            Derived* der = dynamic_cast<Derived*>(ptr);
       }
    }
    Base class is exposed to the word and I dont want to have any implementation of isEqual in the Base class..

    And there are whole bunch of derived class..


    SO... What are my options.?
    Dont forget to rate my post if you find it useful.

  2. #2
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Inheritance and Implementation hiding..

    Quote Originally Posted by code_carnage View Post
    Base class is exposed to the word and I dont want to have any implementation of isEqual in the Base class..
    Code:
    class BASE
    {
        virtual bool isEqual(BASE* ptr) = 0;
    }
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  3. #3
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Inheritance and Implementation hiding..

    You'd be better with something like this.
    Code:
    class BASE
    {
    public:
        virtual bool isEqual(const BASE& rhs) const = 0;
    };
     
    class Derived: public BASE
    {
    public:
       bool isEqual(const Derived& rhs) const
       {  
           return (some_value == rhs.some_value);
       }
    
    private:
        int some_value;
    };
    Actually, having an isEqual member is very 'Java'.
    It would be more normal to overload the == operator.
    Code:
    class BASE
    {
    public:
    
    };
     
    class Derived: public BASE
    {
    public:
    
        Derived()
            : some_value(0)
        {
        }
    
        friend bool operator==(const Derived& lhs, const Derived& rhs);
    
    private:
        int some_value;
    };
    
    bool operator==(const Derived& lhs, const Derived& rhs)
    {  
       return (lhs.some_value == rhs.some_value);
    }
    
    bool operator!=(const Derived& lhs, const Derived& rhs)
    {  
       return !(lhs == rhs);
    }
    
    int main()
    {
        Derived d1;
        Derived d2;
    
        bool same = (d1 == d2);
    }
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  4. #4
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Inheritance and Implementation hiding..

    I can't see any way to avoid the cast unless you're willing to expose the derived classes to the world. You have to use dynamic_cast to find out if the passed ptr really points to the correct (same) derived class.

    Anyway, is this a big problem just because you have a lot of derived classes and don't like all the typing? If so you could create a macro that implements the derived isEqual method based on the == or the != operator. The macro can be placed in the BASE header.

    Something like this:
    BASE.h
    Code:
    class BASE
    {
      ...
      virtual bool isEqual( BASE* ptr ) = 0;
      ...
    };
    #define IMPL_IS_EQUAL( derived )  \
      bool derived::isEqual( BASE* ptr )  \
      { \
        derived* dptr = reinterpret_cast<derived*>( ptr );  \
        return dptr && ( *dptr == *this );  \
      }
    DERIVED.h
    Code:
    class DERIVED1 : public BASE
    {
      ...
      virtual bool isEqual( BASE* ptr );
      ...
    };
    DERIVED.cpp
    Code:
    class DERIVED
    {
      int a;
    public:
      IMPL_IS_EQUAL( DERIVED )
      bool operator == ( DERIVED& p)
      {
        return a == p.a;
      }
    };
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  5. #5
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Inheritance and Implementation hiding..

    [quote=JohnW@Wessex;1998544]You'd be better with something like this.
    Code:
    class BASE
    {
    public:
        virtual bool isEqual(const BASE& rhs) const = 0;
    };
     
    class Derived: public BASE
    {
    public:
       bool isEqual(const Derived& rhs) const
       {  
           return (some_value == rhs.some_value);
       }
    
    private:
        int some_value;
    };
    Hey John, The code above would not compile because isEqual have different signature even though Derived is Derived from BASE.

    Problem will occur when try to create object of Derived class isEqual in derived class will be hidden and base class version is pure virtual..
    Dont forget to rate my post if you find it useful.

  6. #6
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Inheritance and Implementation hiding..

    Quote Originally Posted by S_M_A View Post
    I can't see any way to avoid the cast unless you're willing to expose the derived classes to the world. You have to use dynamic_cast to find out if the passed ptr really points to the correct (same) derived class.

    Anyway, is this a big problem just because you have a lot of derived classes and don't like all the typing? If so you could create a macro that implements the derived isEqual method based on the == or the != operator. The macro can be placed in the BASE header.

    Something like this:
    BASE.h
    Code:
    class BASE
    {
      ...
      virtual bool isEqual( BASE* ptr ) = 0;
      ...
    };
    #define IMPL_IS_EQUAL( derived )  \
      bool derived::isEqual( BASE* ptr )  \
      { \
        derived* dptr = reinterpret_cast<derived*>( ptr );  \
        return dptr && ( *dptr == *this );  \
      }
    DERIVED.h
    Code:
    class DERIVED1 : public BASE
    {
      ...
      virtual bool isEqual( BASE* ptr );
      ...
    };
    DERIVED.cpp
    Code:
    class DERIVED
    {
      int a;
    public:
      IMPL_IS_EQUAL( DERIVED )
      bool operator == ( DERIVED& p)
      {
        return a == p.a;
      }
    };


    Thanks man..Thats what even I concluded..
    Dont forget to rate my post if you find it useful.

  7. #7
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Inheritance and Implementation hiding..

    Quote Originally Posted by code_carnage View Post
    I have to implement a class BASE which is abstarct and has a function called isEqual which ofcourse checks for equality..
    I think you have to be much more precise on the semantics of the function. The implementation suggested by S_M_A seems logical, but can give asymmetric results in a case such as:
    Code:
    class D1 : public BASE;
    class D2 : public D1;
    //...
    int main()
    {
        D1 d1;
        D2 d2;
        if (d1.isEqual(d2)) {
            assert(d2.isEqual(d1)); // what should this do?
        }
    }
    d2 can be cast to a D1, so they could be equal. But d1 cannot be cast to a D2, so should they be considered equal or not?
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Inheritance and Implementation hiding..

    Quote Originally Posted by S_M_A View Post
    I can't see any way to avoid the cast unless you're willing to expose the derived classes to the world. You have to use dynamic_cast to find out if the passed ptr really points to the correct (same) derived class.
    Not actually. You can use a variation on the visitor pattern to obtain the concrete types of both arguments without casting. Something like this:

    Code:
    struct Base
    {
        virtual bool isEqual(const Base &rhs) const = 0;
    };
    
    struct Derived: public Base
    {
        bool isEqual(const Base &rhs) const
        {
            return rhs.isEqual(*this);
        }
        bool isEqual(const Derived &rhs) const
        {
            return state == rhs.state;
        }
        template <typename T>
        bool isEqual(const T &rhs) const
        {
            return false;
        }
    
        T state;
    };
    I'm not 100&#37; positive, but I believe that the rules for overload resolution should guarantee that the template version is not used unless neither of the other two matches.

    Of course, this does require that all derived classes know about each other, which might not be desirable.

  9. #9
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Inheritance and Implementation hiding..

    Quote Originally Posted by Lindley View Post
    Of course, this does require that all derived classes know about each other, which might not be desirable.
    Even worse, the base class needs to know about the derived classes. It must have an overloaded virtual isEqual function for each derived class.

    In your current code, calling isEqual on a pointer or reference to a Base will cause infinite recursion, because the implementation of isEqual in Derived will not call the overloaded function for its own type.
    Quote Originally Posted by Lindley View Post
    Code:
    struct Base
    {
        virtual bool isEqual(const Base &rhs) const = 0;
    };
    
    struct Derived: public Base
    {
        bool isEqual(const Base &rhs) const
        {
            return rhs.isEqual(*this); // *this will be converted to const Base&
        }
        bool isEqual(const Derived &rhs) const
        {
            return state == rhs.state;
        }
        template <typename T>
        bool isEqual(const T &rhs) const
        {
            return false;
        }
    
        T state;
    };
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  10. #10
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Inheritance and Implementation hiding..

    Good point, the base class would at least need forward-declares of each of the derived types. That's typical for Visitor though.

  11. #11
    Join Date
    May 2009
    Posts
    2,413

    Re: Inheritance and Implementation hiding..

    ---
    Last edited by nuzzle; February 19th, 2011 at 02:49 AM.

  12. #12
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: Inheritance and Implementation hiding..

    Oh man I really slipped with that macro! It should of course be dynamic_cast not reinterpret_cast...

    You have a good point there D_Drmmr, I totally missed that nasty side-effect from a deeper inheritance chain. So in order to totally avoid the need of exposing the derived classes the inheritance also has to be restricted to one level and that's quite a big restriction.

    Any other ideas out there? I guess I'm just as curious as code_carnage...
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured