【问题标题】:Compiler error when overriding virtual methods覆盖虚拟方法时出现编译器错误
【发布时间】:2010-04-07 13:50:51
【问题描述】:

使用 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:: 到底是什么,为什么我会看到这些不同的编译器错误?欢迎任何解释!

【问题讨论】:

  • 为什么您首先将所有这些 A:: 放在您的代码中?你想达到什么目的?我认为我从未在这种情况下使用过这种语法(这似乎是一个非常简单的继承)。
  • @Daniel:我承认,我真的不知道自己在做什么。我曾希望,如果有人更改 A 中的虚拟方法名称,那么我会在 B 的覆盖定义中看到编译器错误。省略 A:: 时,编译器不知道我是尝试覆盖 A 的方法还是引入自己的方法,如果 A 处不存在此类方法定义,编译器不会产生错误。这有意义吗?
  • 如果您想要该功能,请使用 C 而不是 C++。 :P
  • @Stefan:你是说你想保证 A 在 B 中实现了一些功能?如果删除 virtual 关键字,则不会覆盖基类。
  • @Stefan:你可能对这个问题感兴趣,然后:stackoverflow.com/questions/497630/…

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


【解决方案1】:
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
}

希望这会有所帮助。

【讨论】:

  • 因为语法是这样的。您不必指定基类名称的两倍。你已经完成了class B: public A。 A::myMethod() 只在你调用 myMethod 时使用,它也应该是静态的。
【解决方案2】:

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;

这样编译器就不会混淆您访问的变量。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      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

      【讨论】:

        【解决方案5】:

        在我看来,您好像尝试将 .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 的实现或 virtual C::ThatFunction() 覆盖 C 的实现。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-19
          • 2020-01-22
          相关资源
          最近更新 更多