CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Sep 2009
    Posts
    4

    Interface class issue

    Hello,
    I'm trying to do something like this:
    - There're Base class and Derived classes.
    - Some Derived classes use multiple inheritance, from Base class and a pure virtual class called Interface. These classes are able of some functionality that ordinary Derived classes aren't.

    Why doesn't it work to cast a enhanced Derived class as a Interface class, and invoke its methods??

    The example below shows exactly what I mean:

    Code:
    int main(void)
    {
       Base       *base     = new Base();
       Base       *polymorph= new Derived();
       Derived   *derived   = new Derived();
    
       cout << " This block works as expected. No problem" << endl << endl;
    
    	base->methodBase();
    	polymorph->methodBase();
    	derived->methodBase();
    	derived->methodInterface();
    
       cout << " The problem begins here" << endl << endl;
    
    	((Interface*)polymorph)->methodInterface();   // <--- Problem is here
            ((Derived*)polymorph)->methodInterface();
    
    	delete base;
    	delete derived;
    	delete polymorph;
    
    	return EXIT_SUCCESS;
    }
    ((Interface*)polymorph)->methodInterface() does not call methodInterface(), but Derived destructor. Which, of course, makes program crash on the next line, as Derived object has been destroyed.

    I need to cast to Interface, because in my real application I have a list of pointers to Base class, and when I find out that some object is indeed, inheriting from Interface, I can think of no other way to call to Interface methods, without casting to every particular enhanced Derived class.
    I use GNU g++.

    I don't know why the above code doesn't work.
    You might think I come from Java, and you'll be right. I don't use Java anymore, since some years ago, but this is the way I would work on it, using interface classes.
    I'm sure there must be another way to go in C++, but I usually like my code to be as much portable as possible, and tend to stay away from language too-much-specific features.

    I'd appreciate ANY comment, help, recommendation.

    Thank you!

  2. #2
    Join Date
    Apr 2008
    Posts
    725

    Re: Interface class issue

    that example doesnt show what you mean because it can't be compiled.

    Code:
    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    public:
    	void methodBase(){std::cout << "base method" << std::endl;}
    };
    
    class Interface
    {
    public:
    	void methodInterface(){std::cout << "interface method" << std::endl;}
    };
    
    class Derived : public Base, public Interface
    {
    };
    
    int main(void)
    {
       Base       *base     = new Base();
       Base       *polymorph= new Derived();
       Derived   *derived   = new Derived();
    
       cout << " This block works as expected. No problem" << endl << endl;
    
    	base->methodBase();
    	polymorph->methodBase();
    	derived->methodBase();
    	derived->methodInterface();
    
       cout << " The problem begins here" << endl << endl;
    
    	((Interface*)polymorph)->methodInterface();   // <--- Problem is here
            ((Derived*)polymorph)->methodInterface();
    
    	delete base;
    	delete derived;
    	delete polymorph;
    
    	return 0;
    }
    output:
    Code:
     This block works as expected. No problem
    
    base method
    base method
    base method
    interface method
     The problem begins here
    
    interface method
    interface method
    whats the problem?

  3. #3
    Join Date
    Sep 2009
    Posts
    4

    Re: Interface class issue

    Full source is attached here (Makefile and exe included).

    My output is

    Code:
     cplus_interfaces.cpp
     Base::methodBase
     Derived::methodBase
     Derived::methodBase
     Derived::methodInterface
     The problem begins here
    Program crashes, as I explained above.
    Attached Files Attached Files

  4. #4
    Join Date
    Sep 2009
    Posts
    4

    Re: Interface class issue

    All source in one file, for simplicity (the same problem occurs)

    Code:
    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
                   Base() {};
       virtual    ~Base() {};
       virtual void methodBase(void)
       {
          cout << " Base::methodBase" << endl;
       }
    };
    
    class Interface
    {
    public:
       /*
                Interface();
       virtual ~Interface();
        */
       virtual void   methodInterface( void ) = 0;
    };
    
    
    class Derived : public Base, public Interface
    {
    public:
                Derived() {};
       virtual ~Derived() {};
    
       virtual void methodInterface( void )
       {
          cout << " Derived::methodInterface" << endl;
       }
    
       void methodBase( void )
       {
          cout << " Derived::methodBase" << endl;
       }
    
    };
    
    
    
    int main(void)
    {
       Base       *base     = new Base();
       Base       *polymorph= new Derived();
       Derived    *derived  = new Derived();
       Interface  *inter;
    
    	cout << " cplus_interfaces.cpp" << endl << endl;
    
    	base->methodBase();
    	polymorph->methodBase();
    	derived->methodBase();
    	derived->methodInterface();
    
    	cout << " The problem begins here" << endl << endl;
    
    	((Interface*)polymorph)->methodInterface();
       ((Derived*)polymorph)->methodInterface();
    
    	delete base;
    	delete derived;
    	delete polymorph;
    
    	return EXIT_SUCCESS;
    }

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

    Re: Interface class issue

    Quote Originally Posted by patroclus View Post
    All source in one file, for simplicity (the same problem occurs)
    Here,

    ((Interface*)polymorph)->methodInterface();

    You cast from Base* to Interface* which is wrong because these types are unrelated.

    Instead you have to go via Derived* like,

    ((Interface*)((Derived*)polymorph))->methodInterface();

    The explicit downcast from Base* to Derived* is necessary but the upcast to Interface* isn't. That's because an upcast is always typesafe.

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

    Re: Interface class issue

    The difficulty is that you're trying to simply reinterpret the pointer. While this would usually work for single inheritance since the memory layout puts the base class first on most compilers, multiple inheritance is more complicated.

    Rather than using the C-style cast, try using a dynamic_cast and see if that solves your problem.

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

    Re: Interface class issue

    Quote Originally Posted by patroclus View Post
    You might think I come from Java, and you'll be right. I don't use Java anymore, since some years ago, but this is the way I would work on it, using interface classes.
    I'm sure there must be another way to go in C++, but I usually like my code to be as much portable as possible, and tend to stay away from language too-much-specific features.
    It's fine to use multiple inheritance of type in C++ too. But note that your code wouldn't have worked in Java either.

    The difference is that in Java you would've got a better error message. In fact I think a Java compiler would've caught this error already at compile-time and said "cast between unrelated types" or something. And even if it hadn't a Java compiler would've put in code to check the downcast at runtime and provided a proper "bad cast" message. To get that in C++ you need to use one of the new casts, namely dynamic_cast.
    Last edited by nuzzle; September 26th, 2009 at 10:40 AM.

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

    Re: Interface class issue

    According to this:
    http://msdn.microsoft.com/en-us/library/cby9kycs.aspx

    dynamic_cast is capable of cross-casting. I wasn't sure, but every source I've looked at says it is.

    Personally I avoid multiple inheritance whenever I can. It's rarely necessary if the design is good, particularly given the capabilities of templates.

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

    Re: Interface class issue

    Quote Originally Posted by Lindley View Post
    Personally I avoid multiple inheritance whenever I can. It's rarely necessary if the design is good, particularly given the capabilities of templates.
    In Java multiple inheritance (of type) is a way of life really. Having a Java background myself I can understand that the OP wants to continue using this programming style. It's how you realise the first rule of OO, namely: Program to an interface, not an implementation (page 18 in Design Patterns by Gamma and others).
    Last edited by nuzzle; September 26th, 2009 at 11:59 AM.

  10. #10
    Join Date
    Sep 2009
    Posts
    4

    Re: Interface class issue

    Quote Originally Posted by nuzzle View Post
    ((Interface*)polymorph)->methodInterface();

    You cast from Base* to Interface* which is wrong because these types are unrelated.

    Instead you have to go via Derived* like,

    ((Interface*)((Derived*)polymorph))->methodInterface();
    That works perfectly, but it really doesn't do the job, because I need to manually add cast for every single derived class, and not just use a single call for any possible Derived class which implements Interface.

    But
    Code:
    (dynamic_cast<Interface*>(polymorph))->methodInterface();
    Works!
    Don't know if it has any drawback, but it seems to go just fine.

    Quote Originally Posted by nuzzle
    But note that your code wouldn't have worked in Java either.
    Why?
    In Java you always know the type of any object at runtime, and I don't remember having problems with these things

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

    Re: Interface class issue

    Quote Originally Posted by nuzzle View Post
    In Java multiple inheritance (of type) is a way of life really. Having a Java background myself I can understand that the OP wants to continue using this programming style. It's how you realise the first rule of OO, namely: Program to an interface, not an implementation (page 18 in Design Patterns by Gamma and others).
    I'd say that's the first rule of abstraction in general, not just OO. In fact it's the reason I was so hesitant to embrace templates at first-----there's no interface equivalent, you just have to "know" what methods the instantiating class needs to support.

    Concepts were supposed to fix that lack, but I guess we have to wait a while longer for real, language-level support on that front.

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

    Re: Interface class issue

    Quote Originally Posted by patroclus View Post
    Why?
    In Java you always know the type of any object at runtime, and I don't remember having problems with these things
    Well, the reason would be that Base and Interface are unrelated and that can be established already at compiletime. But I cannot swear that this particular cast would've been disallowed in Java. I know there are special rules when interfaces are involved.

    I don't have a Java compiler on my computer so I cannot check it easily and I don't feel motivated enougth to locate the proper section in the Java Language Specification so I drop the issue here if you don't mind.

    Don't know if it has any drawback, but it seems to go just fine.
    The drawback is the usual. Downcasts are not typesafe and generally should be avoided.

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

    Re: Interface class issue

    Quote Originally Posted by Lindley View Post
    Concepts were supposed to fix that lack, but I guess we have to wait a while longer for real, language-level support on that front.
    Yes, it's a pity for generics in C++ that concepts didn't make it. In Stepanov's book Elements of Programming, concepts play an important role but when the time comes to use them in real Template code they're just treated as comments.

    I've located another source and that's Modern C++ Design by Alexandrescu. On page 7 he states that "This analysis suggests that a combination of templates and multiple inheritance could engender a very flexible device, appropriate for creating design elements".

    That's what I wanted to hear from an authoritative source really. At this point I'm not ready to write off OO as crap as Stepanov suggests. But who knows, with concepts in place it's a different story I guess. It would be great if Boost would provide an implementation of concepts.
    Last edited by nuzzle; September 27th, 2009 at 02:29 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