2015-11-04 5 views
9

Verwendung Wenn Sie das folgende Beispiel in msvc kompilieren, bekomme ichVerhalten von qualifizierten Namen private Vererbung

'Interface' nicht zugänglich, weil 'Base' Nutzungen 'privat' zu vererben 'Interface'

in der Zeile markiert mit Error. Wenn der Aufruf an foo mit einem Typenalias des gleichen Typen qualifiziert wird, funktioniert es. Ich habe mit msvc und ideone getestet.

Warum sind die beiden Anrufe nicht gleich?

struct Interface {}; 

template<class T> 
struct Base : private T 
{ 
    void foo() {} 
}; 

using BaseX = Base<Interface>; 

class Derived : Base<Interface> 
{ 
    Derived() { 
     Base<Interface>::foo(); // Error 
     BaseX::foo();    // Works 
    } 
}; 

Ideone

+0

Sieht aus wie ein msvc Bug –

+0

@ DieterLücking, ich habe es versucht mit g ++ 4.9.3 und 'BaseX :: foo();' funktioniert. –

Antwort

5

Injected-Klasse-Namen.

Der Name Interface in den Gültigkeitsbereich der Klasse injiziert Interface, als ob es ein öffentliches Mitglied ist, und wiederum durch Base<Interface> (als privates Mitglied, da Sie private Vererbung verwenden) geerbt.

Wenn Sie Base<Interface>::foo() in Derived, Lookup unqualifizierten Namen für Interface schreiben schaut zuerst auf Derived und seine Basisklasse, findet Interface in der Basisklasse, und dann die Kontrolle Kicks zugreifen, da dieser Name ist private.

Die einfachste Lösung ist nur Base::foo() zu schreiben, oder auch nur foo(), wenn es nicht virtuell ist und Sie planen keine foo() in Derived zu schreiben.

Wenn Sie aus irgendeinem Grund das Template-Argument angeben müssen, schreiben Sie Base<::Interface>.

+1

Warum suchen wir nach Interface? – Barry

+0

@Barry Ähm, du hast 'Base :: foo() geschrieben;' ... nicht sicher, warum du denkst, dass es nicht nachgeschlagen wird. –

+0

@Barry Nun, bevor wir 'foo' nachschlagen, müssen wir wissen, in welchem ​​Umfang wir nachsehen können (oder was' Base 'ist) ... also suchen Sie nach' Base' und 'Interface'. –

Verwandte Themen