2010-04-07 83 views
3

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

回答

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 

這完全是出於爲了使方法聲明,該方法是在範圍之內聲明,自然屬於此範圍:

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

1

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

這樣編譯器就不會在你正在訪問的變量之間感到困惑。

1

你不應該在函數聲明的範圍內聲明類的聲明。錯誤消息未在C++標準中指定。所以,每個編譯器顯然都會產生不同的消息來表達這種奇怪的東西。

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

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的執行,或者使用virtual C::ThatFunction()來覆蓋C的實現。

刪除A類中的所有A::將解決您的編譯問題。