views:

352

answers:

4

Hi,
I just wanted to know whether is this following block of code fully valid in C++:

class A
{
public:
  virtual bool b() = 0;
};

class B
{
public:
  virtual bool b() = 0;
};

class C: public A, public B
{
public:
  virtual bool A::b()
  {
    return true;
  }

  virtual bool B::b()
  {
    return false;
  }
};

Using VS2008 it compiles without any errors, however, on GCC (MinGW) 3.4.5 it gives me errors like

cannot declare member function `A::b' within `C'

on the lines where the virtual methods are implemented. I was curious if this is just generally considered invalid and by C++ standards forbidden code (and in VS it thus works thanks to some MS non-standardized magic), or only a bug or unsupported language feature in the GCC.

Thanks for responses.

+16  A: 

No it's not valid. You can't override them separately like that, because they would have the same signature.

There is a guru of the week about that.

Johannes Schaub - litb
and apart from that the non-virtual dtor is a ticking bomb. but that wasn't the question. :)
wilhelmtell
A: 

The qualified name A::b is not allowed as the name of a member of class C.

Thomas L Holaday
+1  A: 

It should not compile due to parents having the same function name. Furthermore, you aren't suppose to overload the function b more than once.

If you refer to the virtual table created for this:

0(beginning of vtable) - A::b() -> B::b()

You see, since class B has the same function name as class A, it overrides it, thus you have now B::b() to override (since it's still pure). This is due to multiple inheritancy. How would the compiler be able to differenciate between the two (they have the same signature)? Generally, this will fail, because like I just said, the compiler isn't suppose to make decisions, it's supposed to tell you that there is a problem.

It compiles on VS, but have you tried running it (included in a file where it is actually created)? Sometimes, compiler are lazy and don't pop errors on classes that aren't used.

tomzx
>How would the compiler be able to differenciate between the two (they have the same signature)?But this happens also for example when you have class with multiple bases that theirselves have some common parent base (a you often need to use virtual inheritance then). Of course the compiler is not able to differenciate calls to the common methods (if we not use the virtual inheritance) and throws ambiguous-call error, but it can be easily solved by dynamic_cast-ing that class instance to the base class we want. And yes, I'm using it on VS this way and it works with no problems.
RedDragCZ
@RedDragCZ: As far as I've used virtual inheritance, it's only been for cases where you'd have sub-classes inheriting from the same base class. If you look at litb link, the proposed solution is to use what is called auxiliary classes.
tomzx
A: 

Just as an FYI, VC gives the error only when you try to use the b method:

C:\temp\test.cpp(33) : error C2668: 'C::b' : ambiguous call to overloaded function
      C:\temp\test.cpp(23): could be 'bool C::b(void)'
      C:\temp\test.cpp(18): or       'bool C::b(void)'
      while trying to match the argument list '(void)'

And for what it's worth, Comeau's compiler behaves similarly, but with an even more confusing error message:

"C:\temp\test.cpp", line 33: error: no instance of overloaded function "C::b"
          matches the argument list
            object type is: C
      bool z = c.b();
Michael Burr
Yes, I know that, without resolving what b() method was meant to be called it of course won't work, but there is no problem with downcasting the C instance allocated on heap and then calling b() on it like 'dynamic_cast<A*>(c_instance_on_heap)->b()' (which is perfectly applicable because in my own code I use the A and B as interfaces).
RedDragCZ
But the compiler should complain at the attempts to declare the methods, not wait until the method is accessed. I don't know why the compilers use this behavior.
Michael Burr