CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    May 2013
    Posts
    2

    Common base class + abstract interface class

    Hi,

    I have an abstract base class - let's call it MyInterface - and a class that most classes in my program inherit from, let's call it MyBaseclass.

    Let's assume that all my objects inherit MyBaseclass, some of which also inherit MyInterface. Now I want to collect objects in a container class, MyContainerclass. The container class is only interested in objects that implement MyInterface.

    Now I know that all objects that inherit MyInterface also inherit MyBaseclass, but the compiler doesn't know that. MyContainerclass wants to call methods in MyBaseclass, but it collects pointers to MyInterface classes. I can't make MyInterface inherit MyBaseclass, because I will be using classes that I don't want to change (they are part of a framework) that already inherit MyContainerclass. IOW, I can't use virtual inheritance to get a nice inheritance diamond.

    To sum up, I want to create a container class that:
    1. Collects objects that implement MyInterface.
    2. Calls MyBaseclass methods on the collected objects.

    I'm not sure how to solve this... I'd appreciate any help.

    Thanks in advance!

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by Jordgubbe View Post
    I know that all objects that inherit MyInterface also inherit MyBaseclass, but the compiler doesn't know that. MyContainerclass wants to call methods in MyBaseclass, but it collects pointers to MyInterface classes. I can't make MyInterface inherit MyBaseclass,
    You don't want to let MyInterface inherit MyBaseclass but maybe you could let MyInterface define a method which returns a pointer to MyBaseclass? Essentially that method just returns this.

    With such a method you can use any MyInterface object as a MyBaseclass object too (as long as it is a MyBaseclass object of course).
    Last edited by nuzzle; May 28th, 2013 at 03:25 PM.

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

    Re: Common base class + abstract interface class

    You say that you "know" that the stored pointers all are pointers to objects that inherits MyBaseClass but for debug purposes you could use dynamic_cast when returning the pointer. At least in debug builds, in release builds you can use reinterpret_cast or static_cast if you're concerned about the runtime cost.

    http://en.cppreference.com/w/cpp/language/dynamic_cast

    For convenience you might also want to use a smart pointer in the container instead of a bare pointer.

    http://en.cppreference.com/w/cpp/memory or http://www.boost.org/doc/libs/1_53_0.../smart_ptr.htm
    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

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by S_M_A View Post
    dynamic_cast
    Downcasting (including sidecasting as in this case) is bad OO and should preferably be avoided because it's not typesafe.

    In my suggestion it's established by design (and not just a known fact) that every MyInterface object has the MyBaseclass property.
    Last edited by nuzzle; May 29th, 2013 at 12:36 AM.

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by Jordgubbe View Post
    I have an abstract base class - let's call it MyInterface - and a class that most classes in my program inherit from, let's call it MyBaseclass.
    That alone sounds like a design problem to me. The rest of your story doesn't make me think anything else.
    I could be wrong, but based on the information you've given, I'd say your design is bad.
    Quote Originally Posted by S_M_A View Post
    in release builds you can use reinterpret_cast or static_cast if you're concerned about the runtime cost.
    The only use of reinterpret_cast that is guaranteed to work, is when you cast back to the original type (and there is no problem regarding the sizes of both types).
    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

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by D_Drmmr View Post
    I'd say your design is bad.
    Using a top base class is quite common in OO designs actually. In both Java and C# it's even built into the language. The best known C++ example is maybe Qt where every class inherits a common top class called QObject.

    I'm using the top class design strategy to uniformly handle a global memory management scheme based on the Boost intrusive smartpointers. It works very well, almost like full GC. In fact it's only since I started with this I felt really at home with C++. It's simple to use. It's efficient, close to bald pointer usage. Object ownership is a no-brainer. No risk for memory leaks. It's threadsafe. It's not in the way of multiple inheritance. No problems with upcasting. No problems handling this-pointers.

    I wouldn't call the use of top classes bad design. But resorting to downcasting definately is.
    Last edited by nuzzle; May 29th, 2013 at 03:28 AM.

  7. #7
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Common base class + abstract interface class

    What nuzzle suggested in #2 seems like the easiest approach to this. Your statement that any object implementing MyInterface must also be a MyObject can even be enforcerd my requiring the MyInterface to take the MyObject pointer as a constructor parameter.

    It's then impossible to make an interface that isn't an object. And you can implement the "get object from interface" function in the base MyInterface class.

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by nuzzle View Post
    Using a top base class is quite common in OO designs actually. In both Java and C# it's even built into the language. The best known C++ example is maybe Qt where every class inherits a common top class called QObject.
    In Qt the QObject base class is used for the signal/slot mechanism, similar to the approach libsigc uses. I'm not arguing against that design for signal/slot support, but not every type (derived from QObject) needs to have signal/slot support. Besides that QObject offers support for parent/child relationships and general properties. It's clearly designed for convenience (as in, just pack everything that could be useful in there so it's there if you may ever need it); it's not a good design IMO. I occasionally find myself downcasting a widget's parent because of the use of the 'god' QObject class. The parent of a widget should be a widget, not a QObject.
    Quote Originally Posted by nuzzle View Post
    I'm using the top class design strategy to uniformly handle a global memory management scheme based on the Boost intrusive smartpointers. It works very well, almost like full GC. In fact it's only since I started with this I felt really at home with C++. It's simple to use. It's efficient, close to bald pointer usage. Object ownership is a no-brainer. No risk for memory leaks. It's threadsafe. It's not in the way of multiple inheritance. No problems with upcasting. No problems handling this-pointers.
    I wonder if you actually need the top class design for this or if it's just a way to reuse the same implementation (intrusive pointers) for the various classes you implement. Do you ever keep a container of (smart) pointers to top-class instances? If so, what do you do with these without downcasting?
    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

  9. #9
    Join Date
    May 2013
    Posts
    2

    Re: Common base class + abstract interface class

    Hi and thank you all for your comments.

    I have a working solution, but it's far from elegant, and since I'm interested in learning about this - I really want to learn more about design patterns - I will give a little bit more information, and I'd be interested in further comments on the subject.

    First of all, I'm using a game framework called Cocos2d-x. In this API, most classes inherit CCObject which provides reference counting and simple garbage collection. Even the list implementation most commonly used, CCArray, only accepts classes that inherit CCObject.

    I realize that in "real" OO design, one CCObject subclass should always be interchangable with any sibling, but I'm not sure if this is always practical.

    What I wanted to do, and I think my first post made this clear, was to have a container class that required the CCObjects to also implement a certain interface. In my case, the abstract interface class forces the inheriting class to implement keypress handlers - it's like saying "this is a CCObject that also accepts keyboard input".

    I chose this solution to my problem - and I'm aware that this is a... "pragmatic" solution rather than an academic one. :-) :

    My container class collects CCObjects, but in my addObject method, I assert() (using dynamic_cast) that the object implements my interface. I think asserting is the right thing to do, since it makes no sense to try to add objects that won't accept keyboard input - that would almost certainly be a programmer error, and in that case it's best to just "crash".
    Now knowing that all my objects in the container does in fact implement the interface, I just do a
    Code:
    static_cast<MyInterface *>(myCCObject)
    to call the interface functions.

    This works and I'm not sure I'll change it now, but I'd really appreciate constructive comments.

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by D_Drmmr View Post
    I'm not arguing against that design for signal/slot support, but
    One can always argue what should or shouldn't be in a top class. But the fact remains, this design strategy is very common in major OO designs such as Qt and integral to many languages such as Java and C#. Please feel free to consider them bad designs if you wish but appearantly many renowned designers think otherwise.

    I wonder if you actually need the top class design for this or if it's just a way to reuse the same implementation (intrusive pointers) for the various classes you implement. Do you ever keep a container of (smart) pointers to top-class instances? If so, what do you do with these without downcasting?
    Of course I don't need to use the top class approach for my memory management scheme. It's just that it has turned out to be the best way to accomplish what I wanted.

    In my designs I never upcast to this top class (simply because it doesn't expose anything of interest applicationwise) but even if I did I wouldn't downcast. I never put myself in a position where I need to downcast.

    I'm aware of the potential dangers with a top class, especially if it carries implementation. Therefore, a top class should be considered part of the systems software rather than the application. It's a very important design decision because you'll have to live with it for the lifetime of the application. But is it bad design? I don't think so.
    Last edited by nuzzle; May 31st, 2013 at 01:57 AM.

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by Jordgubbe View Post
    I realize that in "real" OO design, one CCObject subclass should always be interchangable with any sibling, but I'm not sure if this is always practical.
    I don't understand what you are saying here. Are you referring to the Liskov substitution principle?
    Quote Originally Posted by Jordgubbe View Post
    My container class collects CCObjects, but in my addObject method, I assert() (using dynamic_cast) that the object implements my interface. I think asserting is the right thing to do, since it makes no sense to try to add objects that won't accept keyboard input - that would almost certainly be a programmer error, and in that case it's best to just "crash".
    Now knowing that all my objects in the container does in fact implement the interface, I just do a
    Code:
    static_cast<MyInterface *>(myCCObject)
    to call the interface functions.
    Have a look at boost::polymorphic_downcast
    Quote Originally Posted by Jordgubbe View Post
    This works and I'm not sure I'll change it now, but I'd really appreciate constructive comments.
    It all depends on how invasive your use of the gaming framework is. If it dictates the design for most of your code, then just follow the ideas behind the framework. If that means MyInterface should inherit from CCObject, so be it. There's no point trying to struggle with a framework that 90% of your code uses.
    If, on the other hand, you only interact with the framework in an isolated section of your code base, then you can roll out your own design for the rest of the code and introduce some wrappers or conversions for interaction with the framework.
    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

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

    Re: Common base class + abstract interface class

    Quote Originally Posted by Jordgubbe View Post
    This works and I'm not sure I'll change it now, but I'd really appreciate constructive comments.
    Well, you should never give up type information you then have to recover using downcasting at runtime.

    Since objects know what type they are you can always ask them for their type. It's what my first suggestion essentially does but the design pattern normally used to accomplish that is called Vistor and it's quite involved.

    Fortunately you can get rid of your problem altogether with a small design change. You just introduce a class, like
    Code:
    class MyCCObject : public CCObject, public MyInterface1, public MyInterface2, public MyInterfaceN {};
    The MyCCObject objects will still be of the CCObject type but also in addition have all the properties represented by the interface types. MyCCObject can be viewed as an application specific extension of CCObject. You then collect MyCCObject objects in the container instead of CCObject objects.

    Then this ugly and not typesafe downcast,
    Code:
    static_cast<MyInterface *>(myCCObject)
    becomes a benign upcast instead and can be removed because upcasts don't have to and shouldn't be explicitly stated.
    Last edited by nuzzle; May 30th, 2013 at 04:58 AM.

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