2009-03-13 12 views
8

Czy możesz mi powiedzieć, dlaczego następujący kod daje mi następujący błąd - wezwanie przeciążony „C (int)” jest niejednoznacznaC++ - Konstruktor przeciążenia - prywatnych i publicznych

Myślę, że od C (char x) jest prywatny, tylko c (float) ctor jest widoczny z zewnątrz, a to powinno być wywołane przez konwersję int do float.

Ale tak nie jest.

class C 
{ 
    C(char x) 
    { 
    } 
public: 
    C(float t) 
    { 
    } 
}; 

int main() 
{ 
    C p(0); 
} 

Odpowiedz

18

Zostało to omówione w "Efektywnym C++" Scotta Meyera. Powodem, dla którego jest to niejednoznaczne, jest to, że chcieli zapewnić, że jedynie zmiana widoczności członka nie zmieni znaczenia już istniejącego kodu w innym miejscu.

W przeciwnym razie załóżmy, że twoja klasa C była gdzieś w nagłówku. Jeśli masz prywatnego członka C (int), kod, który podasz, wywoła C (float). Jeśli, z jakiegoś powodu, członek C (int) został upubliczniony, stary kod nagle wywołałby tego członka, nawet jeśli ani stary kod , ani funkcja, którą wywołał, nie zmieniły się.

EDIT: Więcej powodów:

Co gorsza, załóżmy, że miał 2 następujących funkcji:

C A::foo() 
{ 
    return C(1.0); 
} 

C B::bar() 
{ 
    return C(1.0); 
} 

Te dwie funkcje by nazwać różne funkcje w zależności od tego, czy zarówno foo lub bar został uznany jako znajomego C, lub czy dziedziczy z niego A lub B. Posiadanie identycznego kodu wywoływania różnych funkcji jest przerażające.

(To chyba nie tak dobrze jak umieścić dyskusji Scott Meyera, ale taka jest idea.)

+1

Hmm, to wydawało się wielką wyjaśnienia najpierw. Ale ... nadal możliwe jest stworzenie klasy bez intruza, a potem później, że tak stary kod nagle zaczyna wywoływać nowego członka ... Tak więc ta ochrona tworzy jedynie fałszywe poczucie bezpieczeństwa. –

+0

Dobra uwaga. Dodam więcej. –

7

0 jest typu int. Ponieważ może być niejawnie rzutowany równo na float lub char, wywołanie jest niejednoznaczne. Widoczność jest nieistotna dla tych celów.

Albo umieścić 0.0, 0. lub 0.0f lub pozbyć konstruktora C(char) całkowicie.

Edit: Stosowna część standardu, sekcja 13.3:

3) [...] Ale kiedyś funkcje kandydujące i listy argumentów zostały zidentyfikowane, dobór najlepszych funkcji jest taka sama we wszystkich przypadkach:

  • Najpierw wybrany jest podzbiór funkcji kandydata - te, które mają odpowiednią liczbę argumentów i spełniają określone inne warunki - w celu utworzenia zestawu żywotnych funkcji (13.3.2).
  • Następnie wybrana jest najlepsza realna funkcja na podstawie niejawnych sekwencji konwersji (13.3.3.1) potrzebnych do dopasowania każdego argumentu do odpowiedniego parametru każdej realnej funkcji.

4) Jeśli najlepsza możliwa do zrealizowania funkcja istnieje i jest unikatowa, rozdzielczość przeciążenia kończy się sukcesem i wynikiem jest wynik. W przeciwnym razie zawiodą rozdzielczość, a inwokacja będzie źle sformułowana. Kiedy rozdzielczość przeładowania powiedzie się, a najlepsza możliwa do zastosowania funkcja nie jest dostępna (punkt 11) w kontekście, w którym jest używana, program jest źle sformułowany.

Uwaga: widoczność nie jest częścią procesu selekcji.

+0

Nie odpowiedziałeś na pytanie, dlaczego prywatyzacja nie przechyla rozładowania. –

+0

+1 To jest połowa historii, ale nie odnosi się do widoczności. –

+0

Przejście do upvote dla standardowego cytowania. –

-1

Nie sądzę, że:

C p(0); 

jest konwertowana do:

C(float t) 

prawdopodobnie trzeba zrobić:

C p(0.0f); 
+0

Nie, to nie problem. Możliwa jest niejawna konwersja z '0' do float *. –

Powiązane problemy