Topic: Multiple inheritance of abstract classes with same member functions
Author: blargg@flash.net
Date: 1999/07/11 Raw View
(A copy of this message has also been posted to the following newsgroups:
comp.lang.c++)
In article <3787dd93.2749656@nntp.netcom.ca>, hsutter@peerdirect.com (Herb
Sutter) wrote:
> Alex Goeman <Alex.Goeman@dvvlap.be> wrote: [edited for space]
> >Multiple inheritance of abstract classes with same member functions :
> >Class A { virtual long print()=0; }
> >Class B { virtual long print()=0; };
> >Class C : public A,public B { }
> >
> >How can I know specify two different implementations for virtual function
> >print() in interface A and interface B ?
> >
> >I thought doing it as follows, but it doesn't compile :
> >Class C : public A,public B
> >{
> > virtual long A::print() {...};
> > virtual long B::print() {...};
> > virtual long print() {...};
> >}
> >
> >To situate the problem :
> >Suppose that you have a COM object that exposes two interface that by
> >coincidence have a member function with the same signature (using ATL =>
> >multiple inheritance ) and you want to give two different implementations.
>
> Talk about coincidence... I just presented this exact "Siamese Twin"
> problem (including the reference to COM interfaces!) and its solution
> yesterday at the Application Development 99 show in London, UK. I
> initially covered it as Guru of the Week issue #39 (the problem is still
> at www.peerdirect.com/resources/gotw039a.html, but you'll have to hit
> Deja for the solution -- the above page includes a link to Deja).
The solution involves the obvious intermediate classes between the derived
and both bases:
struct B1 {
virtual void f();
};
struct B2 {
virtual void f();
};
struct D1_ : B1 {
virtual void B1_f() = 0;
virtual void f() {
B1_f();
}
};
struct D2_ : B2 {
virtual void B2_f() = 0;
virtual void f() {
B2_f();
}
};
struct D : D1_, D2_ {
// overrides
virtual void B1_f();
virtual void B2_f();
};
As Herb mentions, D1_ and D2_ may need to define forwarding constructors
to forward constructor arguments to the base classes.
In the solution on Deja, Herb mentions that only one of the functions
needs to be renamed, but I fail to see how that would work, as the
override in the final derived would still override both of the base
functions, including the intermediate one:
struct B1 {
virtual void f();
};
struct B2 {
virtual void f();
};
struct D1_ : B1 {
virtual void B1_f() = 0;
virtual void f() {
B1_f();
}
};
struct D : D1_, B2 {
// overrides
virtual void B1_f();
virtual void f(); // sorry, overrides B1::f *and* B2::f
};
I think the best solution would be templated base classes, as this
wouldn't add an extra virtual call when the derived class overrides would
be final (never overriden in a class derived from it):
// interface.h
struct B1 {
virtual void f();
};
struct B2 {
virtual void f();
};
struct D1_ : B1 {
virtual void f();
};
struct D2_ : B2 {
virtual void f();
};
struct D : D1_, D2_ {
// overrides
void B1_f();
void B2_f();
};
// implementation.cpp
inline void D::B1_f() {
// ...
}
inline void D::B2_f() {
// ...
}
void D1_::f() {
static_cast<D&> (*this).B1_f();
}
void D2_::f() {
static_cast<D&> (*this).B2_f();
}
I made the derived functions inline since they would only be called from
the forwarding functions. One might instead define the forwaring functions
inline in the interface file, and the overrides outline, but this risks
creating the vtables for D1_ and D2_, and definitions of the fowarding
functions, in every file that includes them (this depends on the compiler
implementation, of course).
I used reference casts to remind the compiler that it doesn't need to do
NULL checks when doing a downcast to D that requires a pointer adjustment
(a smart compiler should be able to figure out that this is never NULL in
a conforming program).
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Alex Goeman" <Alex.Goeman@dvvlap.be>
Date: 1999/07/10 Raw View
Multiple inheritance of abstract classes with same member functions :
Class A
{
virtual long print()=0;
}
Class B
{
virtual long print()=0;
};
Class C : public A,public B
{
}
How can I know specify two different implementations for virtual function
print() in interface A and interface B ?
I thought doing it as follows, but it doesn't compile :
Class C : public A,public B
{
virtual long A::print() {...};
virtual long B::print() {...};
virtual long print() {...};
}
To situate the problem :
Suppose that you have a COM object that exposes two interface that by
coincidence have a member function with the same signature (using ATL =>
multiple inheritance ) and you want to give two different implementations.
PS: Could you also be so kind to reply to the author also.
PS: I am using Microsoft VC++
Thanks in advance,
Alex Goeman
Email: e008906@dvvlap.Be
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: hsutter@peerdirect.com (Herb Sutter)
Date: 1999/07/11 Raw View
Talk about coincidence... I just presented this exact "Siamese Twin"
problem (including the reference to COM interfaces!) and its solution
yesterday at the Application Development 99 show in London, UK. I
initially covered it as Guru of the Week issue #39 (the problem is still
at www.peerdirect.com/resources/gotw039a.html, but you'll have to hit
Deja for the solution -- the above page includes a link to Deja).
Herb
Alex Goeman <Alex.Goeman@dvvlap.be> wrote: [edited for space]
>Multiple inheritance of abstract classes with same member functions :
>Class A { virtual long print()=0; }
>Class B { virtual long print()=0; };
>Class C : public A,public B { }
>
>How can I know specify two different implementations for virtual function
>print() in interface A and interface B ?
>
>I thought doing it as follows, but it doesn't compile :
>Class C : public A,public B
>{
> virtual long A::print() {...};
> virtual long B::print() {...};
> virtual long print() {...};
>}
>
>To situate the problem :
>Suppose that you have a COM object that exposes two interface that by
>coincidence have a member function with the same signature (using ATL =>
>multiple inheritance ) and you want to give two different implementations.
---
Herb Sutter (mailto:hsutter@peerdirect.com)
PeerDirect Inc. 2695 North Sheridan Way, Suite 150
www.peerdirect.com Mississauga Ontario Canada L5K 2N6
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/07/11 Raw View
On 10 Jul 99 06:57:53 GMT, Alex Goeman <Alex.Goeman@dvvlap.be> wrote:
>How can I know specify two different implementations for virtual function
>print() in interface A and interface B ?
>
>I thought doing it as follows, but it doesn't compile :
>Class C : public A,public B
>{
> virtual long A::print() {...};
> virtual long B::print() {...};
> virtual long print() {...};
>}
There was an old Guru of the Week that deals with this. I think
it was number thirty-something. You can find these GotW's at
http://www.cntc.com/resources/
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]