2011-08-26 11 views
6

私はC++コンパイラは、この受け付けない理由として困惑している:GCCが与える誤差があるなぜC++コンパイラは、継承されたパブリックメソッドと継承された同じ名前のプライベートメソッドのあいだを曖昧にしませんか?

class Foo { 
    private: void Baz() { } 
    }; 

    class Bar { 
    public: void Baz() { 
    }; 

    class FooBar : public Foo, public Bar { }; 

    void main() { 
    FooBar fb; 
    fb.Baz(); 
    } 

を:

request for member ‘Baz’ is ambiguous 
candidates are: void Bar::Baz() 
       void Foo::Baz() 

が、それは私がバーを望んでいることは明らかではありません:: Foo :: Baz()はプライベートなので、Baz()なぜコンパイラはここで曖昧さを感じませんか?

答えて

7

名前解決は2段階で行われます。最初に名前が検索され、名前がアクセスされているかどうかチェックされます。ルックアップの名前があいまいな場合、アクセスは決して考慮されません。

なぜ、多分それは意図的な言語設計ですが、私は名前を解決するプロセスを簡素化する可能性が高いと思います。このルールはすでに大変複雑です。

+0

これは意図的です。これは、コンパイラをより簡単にするものではありません。反対に、アクセスは追加ステップとしてチェックする必要があるため、非常にやや複雑です。 – curiousguy

3

プライベートメンバーに電話したかったかもしれません(可能だった場合)。

正式には、名前が最初に解決され、最適なオーバーロードが選択されているとの言語規則があります。その後、アクセシビリティのチェックがあります。

1

アクセス制限は継承に影響しません。すべての基本クラスからすべてを継承します。不要なようですが、プライベート関数が仮想で少し変更したバージョンを検討してお使いの場合:

class Base 
{ 
    virtual void secret_power() { /* innocent default */ } 
public: 
    void use_me() { secret_power(); } 
}; 

class Derived : public Base 
{ 
    virtual void secret_power() { /* overriding implementation here */ } 
}; 

を今すぐ任意のBase&のために、あなたは常に非仮想パブリックインターフェイスuse_me()を呼び出すことができますが、あなたの派生クラスで提供しますプライベート仮想による実装

2

これを可能にするには、プライベートメソッドを呼び出すことができるかどうかを検討する必要があります。これが許された場合、そのコール:

fb.Baz() 

を使用すると、パブリックまたはプライベート文脈からそれを呼んでいたかどうかに応じて、完全に異なる機能を持つことができます。そして、それは言語の仕方に本当にインラインではありません。

+1

これは優れた点です。ありがとう! –

1

他の人は言ったように、まず名前を調べ、アクセス制限が適用されます。これを回避するには、希望するメソッドを明示的に呼び出すことで対処できます。

fb.Bar::Baz() 
+0

しかし、修飾構文としては2つのことがあります。1)制御名検索2)動的ディスパッチを無効にする(この特殊なケースではありませんが、可能性があります)。 – curiousguy

関連する問題