8

/przeciążenia Mam klasy, który wygląda mniej więcej tak:Kłopoty z const const rozdzielczości

class ClassA 
{ 
    public: 
    float Get(int num) const; 
    protected: 
    float& Get(int num); 
} 

Poza klasy I wywołania funkcji get().

float foo = classAInstance.Get(i); 

Oczekuję tego, aby zadzwonić do publicznej wersji, ale błędy zamiast Visual Studio OUT:

error C2248: 'ClassA::Get' : cannot access protected member declared in class 'ClassA' 

Kiedy zakomentowanie chronionego przeciążenie i usuwając wszelkie odniesienia do niego, kod kompiluje.

Dlaczego kompilator próbuje użyć elementu niedostępnego, gdy dostępny jest dostępny? Czy istnieje zaakceptowany sposób zmuszenia kompilatora do wyboru właściwego przeciążenia? Czy jest gdzieś odniesienie do reguł rozdzielczości dla funkcji członka?

Odpowiedz

7

To prawda, rozdzielczość przeciążania ma miejsce przed kontrolą dostępności. Sekcja 13.3 normy ([over.match]) mówi:

rozdzielczość przeciążenie jest mechanizmem wyboru najlepszej funkcję nazywamy podano listę wyrażeń, które są być argumenty wywołania oraz zestaw funkcji kandydujących że można wywoływać w oparciu o kontekst połączenia . Kryteriami wyboru najlepszej funkcji są liczba argumentów, jak dobrze argumenty są zgodne z listą typu parametru dla kandydującej funkcji, jak dobrze (dla niestatycznych funkcji składowych) obiekt pasuje do niejawnego parametru obiektu, oraz niektóre inne właściwości funkcji kandydata. [Uwaga: Funkcja wybrana przez rozdzielczość przeciążenia nie może być odpowiednia dla kontekstu. Inne ograniczenia, takie jak dostępność funkcji, mogą sprawić, że jej użycie w kontekście wywoływania będzie źle sformułowane. - nota końcowa]

Zazwyczaj poprawka polega na nadaniu nazwom publicznym i chronionym różnych nazw.


Uwaga ta jest przydatna czasami, na przykład:

class Blah 
{ 
    const std::string& name_ref; 

    Blah(const char*) = delete; 

public: 
    Blah(const std::string& name) : name_ref(name) {} 

    void do_something_with_name_ref() const; 
}; 

std::string s = "Blam"; 
Blah b(s); // ok 

Zauważ, że name_ref będą odczytywane tylko z, więc jest to stosowne, aby to const. Jednak odwołania const mogą wiązać się z tymczasowymi, a powiązanie name_ref z tymczasowym byłoby odwoływaniem zwisającym, powodując niezdefiniowane zachowanie w do_something_with_name_ref().

Blah c("Kablooey!"); // would be undefined behavior 
        // the constructor overload makes this a compile error 

prywatny konstruktor uniemożliwia przeciążenie tymczasowe std::string przed niejawnie skonstruowane i związany.

+0

Przykład wydaje się niebezpieczny. Biorąc pod uwagę 'string func();' i wyrażenie 'Blah b (func())' skompiluje i nadal będzie wyświetlać zwisające odwołanie. Oto moja zasada: * Nigdy * nie zachowuj parametrów "const &".Co mówisz? –

+0

@MartinBa: Na pewno chciałbyś również 'Blah (string &&) = delete;' –

+0

Hm. Pojawia się wtedy pytanie, czy nadal konieczne jest ładowanie "const char". czy parametr "char *" łączy się z 'string const &' lub z 'string &&' version? :-) –

5

Rozdzielczość jest wykonywana jako pierwsza, a kontrola dostępu później.

Jeśli masz przeciążenie zarówno const, jak i non const, jest to rozwiązywane przez stałość obiektu, do którego funkcja jest wywoływana.

Powiązane problemy