2014-12-28 3 views
5

Ich frage mich, warum ein Aufruf an eine statische Funktion mehrdeutig ist, auch wenn einer der beiden offensichtlich unmöglich ist, zu rufen, wie es privat ist. Ich hatte gehofft, ich könnte private/geschützte Vererbung verwenden, um den Compiler zu helfen, die Mehrdeutigkeit zu lösen.Warum löst die private Vererbung keine Mehrdeutigkeit für statische Funktionen auf? (getestet in MSVC)

Ist es spezifisch für MSVC oder ist es irgendwie im Standard spezifiziert?

struct A 
{ 
    static int num() { return 0; } 
}; 

struct B 
{ 
    static int num() { return 1; } 
}; 

struct C : public A, private B 
{}; 

int main() 
{ 
    C::num(); // Ambiguous access of num 
} 

Der Hintergrund ist, dass ich durch vererben es eine Möglichkeit der Wiederverwendung eine Überlastung Verhalten (das in A) in vielen abgeleiteten Klassen (C, D, E, F, G) versuchen, zu halten irgendwie eine Regel von Do not Repeat Yourself.

+5

Zugriffskontrolle * nach * Überladungsauflösung erfolgt –

Antwort

6

Ja, es in dem C++ Standard Abschnitt angegeben ist §3.4 [basic.lookup]

Die Zugriffsregeln (Ziffer 11) werden nur berücksichtigt, wenn Namenssuche und Funktion der Überladungsauflösung (falls zutreffend) ist es gelungen,

Namenssuche nicht über die Zugänglichkeit schert: es sowohl findet A::num und B::num, so gibt es eine Mehrdeutigkeit für den Compiler.

können Sie rufen explizit A::num mit:

C::A::num(); 

Wenn Sie explizit versuchen B::num zu rufen, dann wird Ihr Compiler in der Tat einen Zugriffsfehler emittieren:

C::B::num(); // Error 

Sie können die Basis auch explizit bringen Name in Geltungsbereich innerhalb der abgeleiteten Klasse, die die Mehrdeutigkeit beheben wird:

+0

ich verstehe. So kann ich die Mehrdeutigkeit im Abgeleiteten auf einer pro-Funktionsbasis explizit lösen, aber es gibt keine Möglichkeit zu spezifizieren, dass alle Mitglieder einer Basisklasse Vorrang vor der anderen haben würden, was ich naiv versuchte zu erreichen. Die einzige Möglichkeit besteht darin, "vertikal" zu überladen, wenn das Sinn macht? – N0vember

+0

Ja, das ist richtig. Aber im Allgemeinen sollten Sie zuerst versuchen, Namenskonflikte zu vermeiden (natürlich über nicht virtuelle Mitglieder sprechen), so dass das Problem nicht von vornherein auftritt. – quantdev

+0

Das Beispiel aus dem wirklichen Leben ist nur etwas komplexer: Viele abgeleitete müssen "A :: num" überladen, aber wegen der Ausführlichkeit und 'DRY' erben sie die Überladung von einer anderen Basisklasse.Ich werde mit der 'using' Lösung gehen, da sie weniger ausführlich ist. – N0vember

1

Private Mitglieder werden absichtlich für die Überladungsauflösung berücksichtigt.

Angenommen, Sie

class C { 
public: 
    static void f(int); 
    static void g(); 
private: 
    static void f(long); 
}; 

void C::g() { 
    f(0L); // okay 
} 
void g() { 
    f(0L); // error, does not silently call f(int) 
} 

machen nur öffentlich-Mitgliedern zur Verfügung haben bei Überlast Auflösung sehr überraschend Neuinterpretationen von Code verursacht, in dem Code, der wie es aussieht, würde genau die gleiche Art und Weise funktionieren sollte geräuschlos unterschiedliche Überlastungen nennen.

Einen solchen Code als Fehler zu betrachten wurde als weniger problematisch angesehen als die Alternative.

3

Compiler Damit Sie können dies tun,

struct C : public A, private B 
{ 
     using A::num; 
}; 
Verwandte Themen