Rozumiem najwięcej przeciążanie operatora, z wyjątkiem operatorów dostępowych członkiem ->
, .*
, ->*
itd.
W szczególności, co jest przekazywane do tych funkcji operatora, a co powinno zostać zwrócone?
W jaki sposób operator funkcjonuje (np. operator->(...)
) Wie, do którego elementu członkowskiego się odwołuje? Czy to może wiedzieć? Czy to w ogóle musi wiedzieć?
Wreszcie, czy są jakieś względy, które należy wziąć pod uwagę? Na przykład, gdy przeciążasz coś takiego operator[]
, generalnie będziesz potrzebować zarówno wersji stałej, jak i innej. Czy operatorzy dostępu do elementów członkowskich wymagają wersji const i non-const?
c++
operator-overloading
c++-faq
Bingo
źródło
źródło
const
aconst
wersjeoperator->
nie są wymagane , ale podanie obu może być przydatne.->*
i.*
. W rzeczywistości nawet o nich nie wspomina! Wydaje mi się, że rzadko pojawiają się w FAQ, ale chętnie podam link do tego pytania z FAQ. Proszę nie zamykać tego jako oszustwa z FAQ!Odpowiedzi:
->
To jedyny naprawdę trudny. Musi to być niestatyczna funkcja składowa i nie pobiera żadnych argumentów. Wartość zwracana jest używana do wyszukiwania elementu członkowskiego.
Jeśli zwracana wartość jest innym obiektem typu klasy, a nie wskaźnikiem, to kolejne wyszukiwanie elementu członkowskiego jest również obsługiwane przez
operator->
funkcję. Nazywa się to „zachowaniem drążenia w dół”. Język łączy ze sobąoperator->
wywołania, aż ostatnia zwróci wskaźnik.struct client { int a; }; struct proxy { client *target; client *operator->() const { return target; } }; struct proxy2 { proxy *target; proxy &operator->() const { return * target; } }; void f() { client x = { 3 }; proxy y = { & x }; proxy2 z = { & y }; std::cout << x.a << y->a << z->a; // print "333" }
->*
Ten jest podstępny tylko dlatego, że nie ma w nim nic specjalnego. Wersja bez przeciążenia wymaga obiektu wskaźnika do typu klasy po lewej stronie i obiektu wskaźnika do typu elementu członkowskiego po prawej stronie. Ale kiedy go przeładujesz, możesz wziąć dowolne argumenty i zwrócić wszystko, co chcesz. Nie musi nawet być członkiem niestatycznym.
Innymi słowy, ten jest po prostu normalnym operatorem, jak
+
,-
i/
. Zobacz także: Czy wolny operator -> * przeciąża zło?.*
i.
Nie można ich przeciążać. Istnieje już wbudowane znaczenie, gdy lewa strona jest typu klasowego. Być może miałoby to trochę sensu, gdyby można było je zdefiniować dla wskaźnika po lewej stronie, ale komitet projektujący język zdecydował, że byłoby to bardziej zagmatwane niż przydatne.
Przeciążenia
->
,->*
,.
, i.*
może wypełnić tylko w przypadku, gdy wyrażenie będzie niezdefiniowana, to nigdy nie może zmienić znaczenie wyrażenia, które byłyby ważne bez przeciążenia.źródło
new
operatora, nawet jeśli jest on prawidłowy, nawet jeśli nie jest przeciążony.new
jest zawsze przeciążony lub reguły przeciążania tak naprawdę go nie dotyczą (13.5 / 5: Funkcje alokacji i zwalniania alokacji, operator new, operator new [], operator delete i operator delete [], są opisane całkowicie w 3.7 0,4. atrybuty i ograniczenia znajdują się w dalszej części tego podrozdziału nie stosują się do nich, chyba że wyraźnie zaznaczono w 3.7.4). Ale przeciążenia jednoskładnikowa&
lub binarny&&
,||
lub,
, lub dodając przeciążeńoperator=
lub przeciążenia czegokolwiek dla unscoped typ wyliczenia, może zmienić znaczenie wyrażenia. Wyjaśniłem oświadczenie, dzięki!Operator -> jest wyjątkowy.
„Ma dodatkowe, nietypowe ograniczenia: musi zwrócić obiekt (lub odniesienie do obiektu), który również ma operator wyłuskiwania wskaźnika, lub musi zwrócić wskaźnik, który może być użyty do wybrania tego, na co wskazuje strzałka operatora wyłuskiwania wskaźnika. " Bruce Eckel: Thinking CPP Vol-One: operator->
Dodatkowa funkcjonalność jest zapewniona dla wygody, więc nie musisz dzwonić
Możesz po prostu zrobić:
To sprawia, że operator -> różni się od innych przeciążeń operatorów.
źródło
Nie można przeciążyć dostępu do członków
.
(tj. Drugiej części tego, co->
robi). Możesz jednak przeciążać jednoargumentowy operator wyłuskiwania*
(czyli pierwszą część tego, co->
robi).Operator C ++
->
jest w zasadzie połączeniem dwóch kroków i jest to jasne, jeśli uważasz, żex->y
jest to równoważne(*x).y
. C ++ pozwala dostosować, co zrobić z(*x)
częścią, gdyx
jest instancją Twojej klasy.Semantyka
->
przeciążania jest nieco dziwna, ponieważ C ++ umożliwia albo zwrócenie zwykłego wskaźnika (który zostanie użyty do znalezienia wskazanego obiektu), albo zwrócenie instancji innej klasy, jeśli ta klasa również udostępnia->
operator. W tym drugim przypadku wyszukiwanie wyłuskowanego obiektu jest kontynuowane z tej nowej instancji.źródło
->*
, ponieważ jest równoważne z formą(*x).*
?->
Operator nie wie co jest członek wskazał, że tylko zapewnia obiektu do przeprowadzenia rzeczywistego dostępu członkowskich w sprawie.Ponadto nie widzę powodu, dla którego nie można zapewnić wersji const i non-const.
źródło
Kiedy przeciążasz operator -> () (żadne argumenty nie są tutaj przekazywane), kompilator w rzeczywistości wywołuje -> rekurencyjnie, dopóki nie zwróci rzeczywistego wskaźnika do typu. Następnie używa prawidłowego elementu członkowskiego / metody.
Jest to przydatne na przykład do tworzenia inteligentnej klasy wskaźnika, która hermetyzuje rzeczywisty wskaźnik. Wywoływany jest przeciążony operator->, robi to, co robi (np. Blokowanie w celu zapewnienia bezpieczeństwa wątków), zwraca wewnętrzny wskaźnik, a następnie kompilator wywołuje -> dla tego wewnętrznego wskaźnika.
Jeśli chodzi o stałość - odpowiedziano na to w komentarzach i innych odpowiedziach (możesz i powinieneś podać oba).
źródło