This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: [C++]: Multiple inheritage/Conflicts
Hi,
On Sun, Nov 07, 2010 at 12:13:29PM -0800, denilsson31 wrote:
>
> First of all, thank you, Axel for answering.
>
> Yes, this was my first guess regarding the compiler's message.
>
> But, see again my trivial example. It's exactly the same design. Try
> compiling. And it's troublesome.
I think we misunderstand each other: Your trivial example has a
fundamental difference -- the missing "virtual":
a) in the real example, you derive "TemporaryDbFile" from "QFile" and
"dbFile", where:
- QFile has a virtual function "close()" returning "void"
- dbFile has a virtual function "close()" returning "int" (even a pure one)
Now, when you define a function "close()" in the derived class
"TemporaryDbFile" this function:
- has to return "void", as it overrides the virtual function from QFile
- has to return "int", as it overrides the virtual function from dbFile
==> this CAN'T work ;-)
b) in the trivial example, you derive "C" from "A" and "B", where:
- "A" has a NON-virtual function "close()" returning "void"
- "B" has a virtual function "close()" returning "int" (even a pure
one)
Now, when you define a function "close()" in the derived class "C", this
function:
- HIDES "A::close()" (as A::close is NOT Virtual)
- has to return "int", as it overrides the virtual function from "B"
==> everything works.
Try the following code to see what I mean -- the function "A::close()"
is NOT overridden by "C::close()", the function "B::close()" IS:
#include <iostream>
class A {
public:
void close() { std::cout << "A" << std::endl;}
};
class B {
public:
virtual int close() = 0;
};
class C :public A, public B
{
public:
int close()
{
std::cout << "C" << std::endl;
return 0;
}
};
int main()
{
C c;
A &a = c;
B &b = c;
std::cout << "Use a:";
a.close();
std::cout << "Use b:";
b.close();
std::cout << "Use c:";
c.close();
}
When calling "b.close" or "c.close()", the code outputs "C" (as expected
for virtual functions). However, when calling "a.close()", it outputs
"A" (as A::close is NO virtual function!).
a.close() returns "void", b.close() and c.close() return "int"
If you would change the "void close()" in class A also to a virtual
function, the code won't compile anymore.
So I think the only solution will be something like the trick suggested
by Dario
Axel
>
>
> Axel Freyn wrote:
> >
> > Hi,
> >
> > I think your code is no valid C++:
> > On Sun, Nov 07, 2010 at 09:17:56AM -0800, denilsson31 wrote:
> >> Hi,
> >>
> >> I'm developping in Qt and I'm experiencing some compilation errors I
> >> can't
> >> correct.
> >> I define a class, TemporaryDbFile that is a QFile's and dbFile's
> >> derivate.
> >>
> >> QFile is defined like this:
> > (I corrected some typos in your code)
> >>
> >> class QFile {
> >> public:
> >> virtual void close();
> >> };
> >> class dbFile {
> >> public:
> >> virtual int close() = 0;
> >> };
> >>
> >> So, TemporaryDbFile has the duty to implement dbFile's interface with
> >> QTemporaryFile (derivated from QFile) :
> >>
> >> class TemporaryDbFile :public QFile, public dbFile
> >> {
> >> int close() { }
> >> };
> >>
> >> But in this nice picture, there is a sand grain : the gcc compiler 4.4.0.
> >> He tells, mockingly :
> >>
> >> TemporaryDbFile.h:42:error: conflicting return type specified for
> >> 'virtual
> >> int TemporaryDbFile::close()'
> >> C:\Qt\2010.03\qt\include\QtCore\..\..\src\corelib\io\qfile.h:148:error:
> >> overriding 'virtual void QFile::close()'
> > The critical point is: The base-class "QFile" defines "close" to be a
> > VIRTUAL function! So, when you define "int close()" in the derived
> > class, C++ believes you want to override the virtual function defined in
> > the base classes: those defined in QFile AND in dbFile. However,
> > "close()" in QFile has a different return type as the one defined in
> > TemporaryDbFile ==> Thus the error message from the compiler.
> >>
> >> Nevertheless, this minimalist sample, representative of my concern is
> >> accepted by the compiler:
> >>
> >> class A {
> >> public:
> >> void close() {}
> >> };
> >>
> >> class B {
> >> public:
> >> virtual int close() = 0;
> >> };
> >>
> >>
> >> class C :public A, public B
> >> {
> >> public:
> >> int close()
> >> {
> >> A::close();
> >> return 0;
> >> }
> >> };
> > In this example, you ommitted the "virtual" in class A, thus defining in
> > class A a non-virtual function. If you define now "int close()" in class
> > C, this new function will override the non-virtual function "void
> > close()" from class A (which is perfectly fine).
> >
> > So, to state it differently:
> > 1) If you create a "TemporaryDbFile" and access it as QFile:
> > QFile &q = TemporaryDbFile();
> > q.close()
> > Here, the caller expects that "close" returns "void"; however
> > (QFile::close() beeing a virtual function) the code will call
> > "TemporaryDbFile::close()" which returns an integer ==> that's why the
> > compiler won't compile this code.
> >
> > 2) if you create a "C" and access it as A:
> > A& a = C();
> > a.close();
> > Here, as "A::close()" is NO virtual function, the code will just execute
> > "A::close()" (which returns void), completely ignoring the "C::close()"
> > returning an int ==> everything works fine and the code compiles.
> >
> > So, I think you have to decide what the code shall do -- and then
> > correct your code
> >
> > (At least, thats what I think -- Maybe I'm wrong with my interpretation
> > of the virtual functions mechanisms here -- I don't have a C++-Standard
> > handy...)
> >
> >
> > HTH,
> >
> > Axel
> >
> >