Inherit an implementation

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • disown
    New Member
    • Nov 2008
    • 17

    Inherit an implementation

    Hi all. I have a scenario where i have two interfaces, IA and IB. IB is an extension of IA. I also have two implementations of the said interfaces, AImpl and BImpl. I let BImpl inherit from AImpl in order to take care of the IA implementation part of IB. I have used this technique before in Java, but in C++ (VS and GCC), it seems like the IB methods inherited from IA needs to be re-implemented in BImpl, inheriting from AImpl does not help. Below is an example of what I mean:

    Code:
    #include <cstdio>
    
    class IA { public: virtual void m1() = 0; };
    class IB: public IA { public: virtual void m2() = 0; };
    
    class AImpl: public IA {public: void m1() { printf("m1"); }};
    class BImpl: public IB, public AImpl {public: void m2() { printf("m2"); }};
    
    int main() { BImpl b; b.m2(); return 0; }
    This does not compile, since the compilers say that IB::m1 is not implemented
    in BImpl. What I would like is for BImpl to inherit the implementation of m1 from AImpl, thus making BImpl indirectly implement IB::m1 (an thus all IB). This does not seem to work. What can I do to make this work?

    Thank you in advance
  • r035198x
    MVP
    • Sep 2006
    • 13225

    #2
    That won't work in Java either. To inherit functionality you need to inherit from classes not from interfaces. i.e your BImpl must inherit from AImpl for you to get the functionality in AImpl to be available in BImpl.

    Comment

    • disown
      New Member
      • Nov 2008
      • 17

      #3
      your BImpl must inherit from AImpl for you to get the functionality in AImpl to be available in BImpl
      But it does:

      class BImpl: public IB, public AImpl
      Or did I misinterpret multiple inheritance?

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #4
        What happens when you make those functions 'virtual' in your implementation?

        kind regards,

        Jos

        Comment

        • disown
          New Member
          • Nov 2008
          • 17

          #5
          What happens when you make those functions 'virtual' in your implementation?
          That doesn't help. Virtual is inherited and cannot be undone if I remember correctly. I found the answer however. I am sorry to have wasted you time, but it is always when you decide to post a question that you figure it out :)

          My example is an example of the "dreaded diamond", see http://www.parashift.com/c++-faq-lit...heritance.html, Where IB and AImpl are the middle-level classes.

          In order to solve my problem, I had to use virtual inheritance for IB and AImpl. So (once again in c++), it seems like I need to modify the interface in order to implement it properly :)

          The working solution is:
          Code:
          #include <cstdio>
          
          class IA { public: virtual void m1() = 0; };
          class IB: public virtual IA { public: virtual void m2() = 0; };
          
          class AImpl: public virtual IA { public: virtual void m1() { printf("m1"); } };
          class BImpl: public IB, public AImpl { public: void m2() { printf("m2"); } };
          
          int main() {
                  AImpl a;
                  a.m1();
                  BImpl b;
                  b.m1();
                  b.m2();
                  return 0;
          }
          Maybe there is another way of accomplishing this that doesn't require modifying the IB interface, or maybe there is a guideline that says "always use virtual inheritance when modelling interfaces" or something? Any tips or pointers welcome, still trying to learn...

          Comment

          • disown
            New Member
            • Nov 2008
            • 17

            #6
            Oh, and the extra "virtual" in AImpl::m1 can be removed, I used that to try JosAH's idea.

            Comment

            • weaknessforcats
              Recognized Expert Expert
              • Mar 2007
              • 9214

              #7
              #include <cstdio>

              class IA { public: virtual void m1() = 0; };
              class IB: public IA { public: virtual void m2() = 0; };

              class AImpl: public IA {public: void m1() { printf("m1"); }};
              class BImpl: public IB, public AImpl {public: void m2() { printf("m2"); }};

              int main() { BImpl b; b.m2(); return 0; }


              BImpl inherits from IB which inherits from IA which an abstract base class because IA::m1 is a pure virtual function. This function is not implemented anywhere in IB so BImpl is also an abstract base class and you die in compilation tryin to create an instance of an abstract class.

              Then if you implement m1() in IB you have two m1()'s so in main() b.m1() won't work forcing you to code b.IB::m1().

              Comment

              • disown
                New Member
                • Nov 2008
                • 17

                #8
                I'm trying to use this methodology to hide the implementation of a DLL library from the client. I came from Linux, trying to learn Win for my new work (a bit backwards, I know :) ).

                After doing some research, I've found an equivalent discussion here:
                http://www.archivum.in fo/comp.lang.c++/2008-08/msg00431.html

                It basically suggests to use virtual inheritance when implementing (or extending) interfaces, and that you can ignore the VS warnings you get when you do this. GCC just compiles cleanly without warnings.

                I you are interested in binary encapsulation related to interfaces and C++, another really good read on the topic (surprisingly) turned out to be the first chapter of "Essential COM" by Don Box, you can google "COM as a better C++". This chapter explains that this problem (implementation hiding with interfaces) was basically the rationale behind the decision to invent COM (a windows reusable components framework). COM now seems to have grown plenty of its own complexities, but the good ideas behind it are well explained in that book.

                Thanks everyone for your help.

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  You hide an implementation by using an interface class or a set of interface functions.

                  You do not hide an implentation by using public virtual functions. All virtual functions should be private. The reason for this is that the public members of a base class is the hierarchy interface. Overidding one of those functions, omits that part of the interface in the derived class. Worse, the public virtual function exposes how you implement the feature in your derived class. Worse, it forces all derived classes to support the same functions, even if they don't apply.

                  Check out the Template design pattern.

                  Research separating the interface from the implementation. In this respect Don Box and COM in general is outdated. I know, I know, you see public virtual functions every day. But that is just the argument that if you repeat something often enough, it becomes true.


                  All you provide the use of the DLL is a header file. None of your classes should be exposed. Then if you use the extern "C" feature with your interface functions, you can compile your DLL in C++, using any C++ features or STL goodies, and still make calls into the DLL using a program compiled in C.

                  Comment

                  Working...