2014-12-28 14 views
5

Zastanawiam się, dlaczego wywołanie funkcji statycznej jest niejednoznaczne, nawet jeśli jedno z nich jest oczywiście niemożliwe do wywołania, ponieważ jest prywatne. Miałem nadzieję, że będę mógł używać prywatnego/chronionego dziedziczenia, aby pomóc kompilatorowi rozwiązać niejednoznaczność.Dlaczego prywatne dziedziczenie nie rozwiązuje niejednoznaczności funkcji statycznych? (testowane w MSVC)

Czy jest to specyficzne dla MSVC, czy jest to w jakiś sposób określone w standardzie?

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 
} 

tło jest, że próbuje sposób ponowne przeciążenia zachowania (jeden w A) w wielu klas pochodne (C, D, E, F, G) w dziedziczeniu to, aby stosować jakoś zasada Nie powtarzaj się.

+5

kontrola dostępu odbywa się po * * Rozdzielczość przeciążenie –

Odpowiedz

6

Tak to jest określone w sekcji C++, standardowa §3.4 [basic.lookup]

Zasady dostępu (§ 11) uznaje tylko raz wyszukiwanie nazw i rozdzielczości przeciążenie funkcji (jeśli dotyczy) udało

Nazwa odnośnika nie dba o dostępności: znajdzie zarówno A::num i B::num, więc istnieje niejasność dla kompilatora.

można jawnie wywołać A::num z:

C::A::num(); 

Jeśli wyraźnie spróbować zadzwonić B::num, wówczas kompilator faktycznie emitują błąd dostępu:

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

Można również wyraźnie zgromadzenie podstawy nazwa w zakresie w klasie pochodnej, która rozwiąże niejednoznaczność:

struct C : public A, private B 
{ 
    using A::num;  
}; 
+0

rozumiem. Mogę więc jednoznacznie rozwiązać niejednoznaczność w pochodnych, na podstawie funkcji, ale nie ma sposobu, aby określić, że wszyscy członkowie jednej klasy bazowej mieliby pierwszeństwo nad innymi, co naiwnie próbowałem osiągnąć. Jedynym sposobem jest przeciążenie "w pionie", jeśli ma to jakiś sens? – N0vember

+0

Tak, zgadza się. Ale ogólnie rzecz biorąc, powinieneś najpierw unikać kolizji nazw (oczywiście mówiąc o członkach nie-wirtualnych), więc problem nie występuje w pierwszej kolejności. – quantdev

+0

Prawdziwy przykład życia jest nieco bardziej złożony: wiele wyprowadzonych musi przeciążyć 'A :: num', ale ze względu na szczegółowość i' DRY' odziedziczą przeciążenie z innej klasy bazowej.Pójdę z rozwiązaniem 'using', ponieważ jest mniej szczegółowe. – N0vember

1

Członkowie prywatni są świadomie rozważani w celu rozwiązania problemu z przeciążeniem.

Załóżmy, że masz

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) 
} 

Making tylko dla członków publiczne dostępne w rozdzielczości przeciążenie powoduje bardzo zaskakujące reinterpretacje kod, gdzie kod, który wygląda jak to powinno działać w ten sam sposób będzie dyskretnie zadzwonić różnych przeciążeń.

Dokonanie takiego kodu błędu uznano za mniej kłopotliwy niż alternatywa.

3

Aby pomóc kompilator można zrobić

struct C : public A, private B 
{ 
     using A::num; 
}; 
Powiązane problemy