2016-12-01 62 views
6

我意外地在基類結構派生的類中隱藏了一個(基)結構的私有成員的一些成員變量。編譯器不應該爲派生類中的基礎結構的成員變量提出警告嗎?

struct base {
int a;
}

類派生的:公共基礎{
私人:
INT一個;
...

那是在我的情況有誤,造成偷偷摸摸的錯誤(幸好抓住了,而測試)。
因爲我認爲有目標的成員是非常罕見的(如果根本不被認爲是不好的做法),我想知道爲什麼編譯器沒有提出至少一個警告(好吧,不是錯誤,因爲在法律上允許陰影)?

我使用的編譯器是Microsoft Visual C++ 2015,警告級別4)。
我想知道其他編譯器(即GCC)是否爲這種情況提供了特定的警告?

+0

gcc也沒有提供警告,但有趣的是,這種行爲應該如何與多態性整體工作 – Starl1ght

+1

我相信,即使沒有'private',在你的例子中隱藏一個變量,幾乎總是一個錯誤。我爲[clang](https://llvm.org/bugs/show_bug.cgi?id=31222)和[gcc](https://gcc.gnu.org/bugzilla/show_bug.cgi)提交了一項功能請求。 ID = 78632)。 –

+1

@VittorioRomeo在編寫Derived時,如果'Base'中不存在'a'不是錯誤。 –

回答

4

陰影是壞還是壞取決於您引入衝突名稱的順序。

假設你有一個類庫和類之一是這樣的:

struct Base { 
    int a; 
}; 

後來,誰在使用你類庫的顧客A寫道的:

class DerivedA : public Base { 
private: 
    int a; 
}; 

在這種情況下,陰影可能是無意的。客戶意外遮蔽Base::a

但是,假如你也有客戶B,誰寫的:

class DerivedB : public Base { 
private: 
    int b; 
}; 

到目前爲止好。現在,您建立了庫,以便使用Base對象,而使用庫的客戶B構建了一個使用BaseDerivedB對象的代碼體。

幾個星期後,您意識到爲了獲得新功能,您需要添加一個新成員到Base

struct Base { 
    int a; 
    int b; // new member variable 
}; 

這是否會對您的圖書館造成問題?它是否對顧客B造成問題?

不,它不會產生任何問題。

您所有的代碼,使用Base將繼續使用Base,並且它可以使用b成員獲得新奇b功能。即使DerivedB對象被傳遞給期望爲Base的函數,但Derived隱藏的事實bBase沒有影響。您使用Base的函數可以說是b,它將訪問Base成員變量。

同時,所有使用DerivedB將繼續使用DerivedB,當該代碼表示​​b,它得到DerivedB::b,就像它以前那樣客戶B的代碼。嘿,陰影拯救了一天! (當然,如果顧客B想要開始利用新的b功能,那麼顧客B必須做額外的工作來解決衝突,但重要的是影子沒有產生任何新問題在現有代碼中)。

在一天結束時,陰影的好壞取決於引入衝突名稱的順序。這不是編譯器已經洞悉的東西。

+1

對,這不是編譯器已經洞察的東西,但肯定可以是編譯器可以輕鬆警告的人爲錯誤。 如果遮蔽是由派生類的開發者打算並希望的,他們可能會忽略或抑制警告。 在所有這些情況下,我寧可更多的警告而不願意的行爲...... – roalz

+0

@roalz但是,圖書館作者如何在庫本身中引入警告抑制?警告來自客戶B的代碼,圖書館作者無權訪問客戶B的代碼。 –

+0

恕我直言,因爲在「客戶」代碼中引入了影子(想要或不想要),所以可能要由客戶來制止警告。或者我錯過了什麼? – roalz

相關問題