views:

218

answers:

5

Using VC71 compiler and get compiler errors, that i don't understand. Here comes the example

class A
{
public:
  virtual int& myMethod() = 0;
  virtual const int& myMethod()const = 0;
};

class B: public A
{
public:
  // generates: error C3241: 'const int &B::myMethod(void)' : this method was not introduced by 'A'
  virtual int&  A::myMethod();

  // error C2555: 'B::myMethod': overriding virtual function return type differs and is not covariant from 'A::myMethod'
  virtual const int& A::myMethod() const;
};

when i switch order of both method definitions in B then I see a different compiler error:

class B: public A
{
public:
  // error C3241: 'const int &B::myMethod(void)' : this method was not introduced by 'A'
  virtual const int& A::myMethod() const;

  // error C2556: 'int &B::myMethod(void)' : overloaded function differs only by return type from 'const int &B::myMethod(void)'
  // error C2373: 'B::myMethod' : redefinition; different type modifiers
  virtual int&  A::myMethod();

  // error C2555: 'B::myMethod': overriding virtual function return type differs and is not covariant from 'A::myMethod'

};

however, if I omit the A:: stuff then i don't get any compiler error:

class B: public A
{
public:
  virtual int&  myMethod();
  virtual const int& myMethod() const;
};

So, what exactly does A:: in front of my method names and why do i see these diverse compiler errors? Any explanation welcome!

+2  A: 
class B: public A
{
public:
  virtual const int& myMethod() const;
  virtual int& myMethod();
};

Remove the A:: in B's definition, and it works well :)

EDIT: missed something in the question...

The :: is used to indicate the scope. You use it either with namespaces or classes to explicitly qualify where to look for the symbol afterwards.

Used in conjunction with methods, it means that you want to precise which method calls, for example:

struct A { int getInt(); }

struct B: public A { int getInt(); }

B b;
b.A::getInt(); // calls A::getInt, not B::getInt

This is completely out of order for a method declaration, the method is declared within a scope and naturally belongs to this scope:

namespace foo
{
  int bar();     // full name is foo::bar
}

struct Foo
{
  static int bar();     // full name is Foo::bar
};

However, it's useful when referring to the mode:

using foo::bar;

int a = bar();    // calls foo::bar because we asked the compiler
                  // to import it in the current scope

Or as we already seen, to directly invoke the method:

int B::getInt()                 // definition outside the class
                                // we need to specify what we define
{
  return this->A::getInt() + 1; // call A::getInt, without precising it
                                // we would have a stack overflow
}

Hope this helps.

Matthieu M.
Right. But I wonder why it is like that?
Stefan Hubert
Because the syntax is like that. You don't have to specify twice the name of the base class. You have done it already `class B: public A`.A::myMethod() is used only when you call myMethod, and it should be also static.
Draco Ater
+1  A: 

The A:: signifies that you're calling a function from A. Here's an example of why you'd want to use A::

class A{
public:
   int m_val;
};

class B{
public:
   int m_val;
};

class C: public A, public B{}

Now when I want to set a value for m_val in C, I'd have to do:

C myC;
myC::A::m_val = 4;

so that the compiler doesn't get confused as between what variable you are accessing.

wheaties
+1  A: 

You're not supposed to scope function declarations inside a class declaration. Error messages are not specified in the C++ standard. So, each compiler will obviously produce different messages for something this bizarre.

Judge Maygarden
A: 

I assume you're doing something like this to handle multiple inheritance, i.e:

class A
{
public:
  virtual int& myMethod() = 0;
};

class A2
{
public:
  virtual int& myMethod() = 0;
};

class B: public A, public A2
{
public:
  virtual int&  A::myMethod();
  virtual int&  A2::myMethod();
};

But it doesn't work that way. B can only have one myMethod(). See here:

http://www.cprogramming.com/tutorial/multiple_inheritance.html

Timmmm
A: 

It looks to me as though you've tried moving a .cpp file contents into a .h file? Those scope declarations would make sense in the .cpp definition file, but shouldn't be there in the .h declaration (as others have alrady pointed out).

// generates: error C3241: 'const int &B::myMethod(void)' : this method was not introduced by 'A'
virtual int&  A::myMethod();

So here you're saying you're using a virtual function which is implementing an interface function which is defined elsewhere. By putting A:: in front of it you're saying that your function is overriding myMethod which is defined in A. If you had two base classes (B and C for arguments sake) which both have a function with the same name, you might use virtual B::ThatFunction() to override B's imlpementation or virtual C::ThatFunction() to override C's implementation.

Removing all the A::'s in the A class will fix your compile problems.

Jon Cage