2012-12-18 52 views
18

請問你能解釋爲什麼下面的代碼編譯和工作正常(在gcc-4.3.4上檢查)。我認爲選擇性遺傳不能削弱或甚至加強對成員/方法的訪問。它不破解封裝規則嗎?選擇性繼承C++

#include <iostream> 

class A { 
protected: 
    void foo() { std::cout << "foo" << std::endl; } 
}; 

class B : private A { 
public: 
    using A::foo; //foo() becomes public?! 
}; 

int main() { 
    B b; 
    b.foo(); 
    return 0; 
} 
+0

+1教我的東西。 –

+1

您在從標準容器私下繼承時執行此操作。基本上,你禁止臨近(這意味着你不需要一個虛擬析構函數),但是你允許一些繁瑣的操作來重新實現/轉發。 –

回答

12

從語言的角度來看,這沒什麼不妥(不管是好設計是另一回事)。

任何班級都可以選擇向更廣泛的受衆公開其可訪問的內容。

原則,你的例子是沒有什麼不同來:

class B : private A { 
public: 
    void bar() { foo(); } 
}; 

但此處foo()由代理暴露。

你不能做的是相反的:公共派生類不能限制對基類可訪問的東西的訪問。

+1

當然可以;在'struct A {int i; }; struct B:A {private:using A :: i; };'B :: i'別名和陰影'A :: i'具有私人訪問權限。當然,這不會阻止你寫'b.A :: i',這也許就是你的意思。 – ecatmur

+1

@ecatmur:'B'可以混淆事物,但它不能限制訪問。我總是可以上傳引用到A和使用A的API:A&a = b; a.i = 42;' – NPE

+0

@ecatmur:我選擇* hide *這個詞有點不幸。我改進了措辭。 – NPE