2012-04-24 191 views
10

我剛剛試過這段代碼:多重繼承:2Classes1Method

struct FaceOfPast 
{ 
    virtual void Smile() = 0; 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() = 0; 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

...

void main() 
{ 
    Janus* j = new Janus(); 
    FaceOfFuture* future = j; 
    FaceOfPast* past = j; 

    future->Smile(); 
    past->Smile(); 

    delete j; 
} 

它按預期工作(輸出兩個笑臉),但我不認爲它應該編譯,Janus中的Smile()重新聲明含糊不清。

它是如何工作的?

回答

7

有沒有歧義,因爲你的指針FaceOfFutureFaceOfPast只聲明一個方法調用Smile()Smile()

因爲調用基類指針的方法可以在不確定性不會導致,讓我們治療的情況下,當你調用該方法直接在子類指針

Janus* j = new Janus(); 
j->Smile(); 

派生類,除了重寫,還隱藏了基類的聲明Smile()。你必須只有當你將不會被覆蓋在派生類中的方法的歧義:

下編譯:

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

雖然你在Janus調用Smile,基類的聲明被隱藏。

下列不:

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
}; 

int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

因爲歧義。

+2

這個問題似乎並不是關於調用部分,而是重新定義的部分:爲什麼您只需編寫一個方法就可以重新定義2個不同類中的同名2個虛函數? – alexisdm 2012-04-24 12:31:54

0
Janus* j = new Janus(); 
FaceOfFuture* future = j; 
FaceOfPast* past = j; 

這部分代碼轉換爲基類。所以,當你做到以下

future->Smile(); 
past->Smile(); 

這是實際的指針,FaceofPast和FaceOfFuture。

1

根據C++標準(10.3.2):

如果虛擬成員函數VF在類基地和派生類聲明的,直接或間接地來源於基地 ,一個成員函數VF具有相同名稱,參數類型列表,CV-資格,和ref-限定符(或不存在的相同)基地:: VF被聲明,那麼派生:: VF [ ...覆蓋Base :: vf

似乎沒有成爲多重繼承任何特殊待遇,所以它最有可能得申請在這裏:void Janus::Smile()覆蓋這兩種方法沒有任何含糊,只是因爲它具有完全相同的名稱和簽名既是基類方法。