This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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
> > 
> > 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]