覆盖虚拟方法时编译错误

问题描述:

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

当i开关在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::,为什么我看到这些不同compil呃错误?任何解释欢迎!

+0

_你为什么把所有的A ::'放在你的代码中?你想达到什么目的?我不认为我曾经在这种情况下使用过这种语法(这似乎是一个非常简单的继承)。 – 2010-04-07 13:56:47

+0

@丹尼尔:我承认,我不知道,我在做什么。我希望,如果有人会改变A中的虚拟方法名称,那么我会在B的覆盖定义中看到编译器错误。当省略A ::时,编译器不知道我是否尝试覆盖A的方法或引入自己的方法,并且如果在A处不存在这样的方法定义,则编译器不会产生错误。这是否有意义? – 2010-04-07 14:06:19

+0

如果您需要该功能,请使用C而不是C++。 :P – 2010-04-07 14:11:07

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 

这完全是出于为了使方法声明,该方法是在范围之内声明,自然属于此范围:

using foo::bar; 

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

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

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

但是,它指的是模式的时候很有用

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

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 
} 

希望这有助于。

+0

对。但我想知道为什么它是这样的? – 2010-04-07 14:08:18

+0

因为语法就是这样。您不必指定两次基类的名称。你已经做了'B类:公共A'。 A :: myMethod()仅在您调用myMethod时使用,它也应该是静态的。 – 2010-04-07 14:24:10

的A ::意味着你调用从A函数下面是为什么你要使用A ::

class A{ 
public: 
    int m_val; 
}; 

class B{ 
public: 
    int m_val; 
}; 

class C: public A, public B{} 

现在,当我想为m_val值的例子在C中,我必须这样做:

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

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

你不应该在函数声明的范围内声明类的声明。错误消息未在C++标准中指定。所以,每个编译器显然都会产生不同的消息来表达这种奇怪的东西。

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

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

在我看来,就好像你已经尝试过移动.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::将解决您的编译问题。