覆盖虚拟方法时编译器错误

时间:2010-04-07 13:50:52

标签: c++ visual-c++ compiler-errors

使用VC71编译器并获取编译器错误,我不明白。 这是示例

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

当我在B中切换两个方法定义的顺序时,我看到了不同的编译器错误:

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'

};

但是,如果我省略了A::的东西,那么我不会得到任何编译器错误:

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

那么,在我的方法名称前面A::究竟是什么呢?为什么我会看到这些不同的编译器错误?欢迎任何解释!

5 个答案:

答案 0 :(得分:2)

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

删除B定义中的A::,效果很好:)

编辑:错过了问题中的内容......

::用于表示范围。您可以使用命名空间或类来明确限定之后查找符号的位置。

与方法结合使用,意味着您需要精确调用哪些方法,例如:

struct A { int getInt(); }

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

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

对于方法声明,这完全不正常,该方法在范围内声明,并且自然属于此范围:

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

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

但是,在引用模式时它很有用:

using foo::bar;

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

或者正如我们已经看到的那样,直接调用方法:

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
}

希望这有帮助。

答案 1 :(得分:1)

A ::表示你正在从A调用一个函数。这是一个你想要使用A ::

的原因的例子。
class A{
public:
   int m_val;
};

class B{
public:
   int m_val;
};

class C: public A, public B{}

现在,当我想在C中为m_val设置一个值时,我必须这样做:

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

这样编译器就不会在你正在访问的变量之间感到困惑。

答案 2 :(得分:1)

您不应该在类声明中对函数声明进行范围化。错误消息未在C ++标准中指定。因此,每个编译器显然会为这个奇怪的东西产生不同的消息。

答案 3 :(得分:1)

我假设你正在做这样的事情来处理多重继承,即:

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();
};

但它不会那样工作。 B只能有一个myMethod()。见这里:

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

答案 4 :(得分:0)

在我看来,您似乎已尝试将.cpp文件内容移动到.h文件中?那些范围声明在.cpp定义文件中是有意义的,但不应该在.h声明中(正如其他人已经指出的那样)。

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

所以在这里你说你正在使用一个虚函数,它正在实现一个在别处定义的接口函数。通过将A::置于其前面,您说您的函数正在覆盖A中定义的myMethod。如果您有两个基类(BC为参数),它们都具有相同名称的函数,您可以使用virtual B::ThatFunction()来覆盖B的imlpementation或virtual C::ThatFunction()覆盖C的实现。

删除A类中的所有A::将解决编译问题。