By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,952 Members | 1,416 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,952 IT Pros & Developers. It's quick & easy.

Inherit an implementation

P: 17
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:

Expand|Select|Wrap|Line Numbers
  1. #include <cstdio>
  2.  
  3. class IA { public: virtual void m1() = 0; };
  4. class IB: public IA { public: virtual void m2() = 0; };
  5.  
  6. class AImpl: public IA {public: void m1() { printf("m1"); }};
  7. class BImpl: public IB, public AImpl {public: void m2() { printf("m2"); }};
  8.  
  9. int main() { BImpl b; b.m2(); return 0; }
  10.  
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
Nov 13 '08 #1
Share this Question
Share on Google+
8 Replies


10K+
P: 13,264
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.
Nov 13 '08 #2

P: 17
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?
Nov 13 '08 #3

Expert 10K+
P: 11,448
What happens when you make those functions 'virtual' in your implementation?

kind regards,

Jos
Nov 13 '08 #4

P: 17
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:
Expand|Select|Wrap|Line Numbers
  1. #include <cstdio>
  2.  
  3. class IA { public: virtual void m1() = 0; };
  4. class IB: public virtual IA { public: virtual void m2() = 0; };
  5.  
  6. class AImpl: public virtual IA { public: virtual void m1() { printf("m1"); } };
  7. class BImpl: public IB, public AImpl { public: void m2() { printf("m2"); } };
  8.  
  9. int main() {
  10.         AImpl a;
  11.         a.m1();
  12.         BImpl b;
  13.         b.m1();
  14.         b.m2();
  15.         return 0;
  16. }
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...
Nov 13 '08 #5

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

weaknessforcats
Expert Mod 5K+
P: 9,197
#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().
Nov 13 '08 #7

P: 17
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.info/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.
Nov 14 '08 #8

weaknessforcats
Expert Mod 5K+
P: 9,197
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.
Nov 14 '08 #9

Post your reply

Sign in to post your reply or Sign up for a free account.