2012-12-18 15 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; };構造体B:A {プライベート: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