Kiedy używasz słowa kluczowego „to”? [Zamknięte]


249

Byłem ciekawy, jak inni ludzie używają tego słowa kluczowego. Zwykle używam go w konstruktorach, ale mogę go również używać w całej klasie w innych metodach. Kilka przykładów:

W konstruktorze:

public Light(Vector v)
{
    this.dir = new Vector(v);
}

Gdzie indziej

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}

2
Znalazłem dobre przykłady, kiedy naprawdę potrzebujesz this w MSDN. Podążaj za tym linkiem ... ;-)
Matt

12
Jeśli musisz zrozumieć i zoptymalizować lub przepisać kogoś innego, w większości źle napisany kod, chętnie byś miał thislub inny kwalifikator, aby po prostym spojrzeniu poznać zakres zmiennej (szczególnie pominięte kwalifikatory klasy dla stałych (ten sam pakiet lub hierarchia) lub super/ basekwalifikatory). A używanie powszechnie stosowanej składni jak _foonie wydaje mi się takie eleganckie. Naciskanie _na intellisense zajmuje więcej czasu niż wchodzenie this. I po co w ogóle zawracać sobie tym głowę! Dzięki funkcjom formatowania automatycznego zapisywania Eclipse nie ma potrzeby, _jeśli zapomnisz kwalifikatora.
djmj

Po przeczytaniu poniższych odpowiedzi i komentarzy, a także przeczytaniu dokumentacji MSDN: docs.microsoft.com/en-us/previous-versions/visualstudio/... na temat tego słowa kluczowego, które nie było aktualizowane od 6 lat, sugerowałbym aby nigdy nie używać tego słowa kluczowego. To bezcelowe. Nie rób parametrów o tej samej nazwie, jest to mylące i głupie. Dlaczego chcesz to zrobić? Ponadto, nie przechodzą instancję w korzystaniu z tego , to również mylące i głupie.
Yusha,

Odpowiedzi:


218

Istnieje kilka zastosowań tego słowa kluczowego w języku C #.

  1. Aby zakwalifikować członków ukrytych pod podobną nazwą
  2. Aby obiekt przekazywał się jako parametr do innych metod
  3. Aby obiekt zwrócił się z metody
  4. Aby zadeklarować indeksatorów
  5. Aby zadeklarować metody rozszerzenia
  6. Aby przekazać parametry między konstruktorami
  7. Aby ponownie przypisać wewnętrznie wartość typu (struct) wartość .
  8. Aby wywołać metodę rozszerzenia w bieżącej instancji
  9. Aby rzucić się na inny typ
  10. Do łączenia konstruktorów zdefiniowanych w tej samej klasie

Możesz uniknąć pierwszego użycia, nie posiadając zmiennych członkowskich i lokalnych o tej samej nazwie w zakresie, na przykład postępując zgodnie z powszechnymi konwencjami nazewnictwa i używając właściwości (przypadek Pascala) zamiast pól (przypadek wielbłąda), aby uniknąć kolizji ze zmiennymi lokalnymi (również wielbłąd walizka). W C # 3.0 pola można łatwo przekonwertować na właściwości za pomocą automatycznie zaimplementowanych właściwości .


49
8. Aby wywołać metodę rozszerzenia dla bieżącej instancji ( this.Foo();zadziała, ale Foo()nie zadziała)
Marc Gravell

4
Również rzucić się do innego typu, na przykład wyraźnie realizowane metoda zostanie wywołana niczym ((ICollection<T>)this).Add(bla).
nawfal

4
Aby połączyć konstrukcję z innym konstruktorem zdefiniowanym w tym samym typie. public ClassName(...) : this(...).
Lasse V. Karlsen

1
@I to nie wpłynie na wydajność w czasie wykonywania. Zakładając, że nie ma dwuznaczności, dane wyjściowe kompilatora są takie same, niezależnie od tego, czy piszesz, na przykład, this.someField = someValueczy someField = someValue. Może to wpłynąć na wydajność kompilatora, ponieważ kompilator będzie analizował kod źródłowy inaczej, ale każda różnica z pewnością byłaby znikoma.
phoog

7
Możesz uniknąć pierwszego problemu, uzyskując dostęp do pól poprzez właściwości tylko wtedy, gdy przestrzegasz konwencji stylu, w której właściwości nie mogą mieć takich samych nazw jak parametry. Zdarza się, że konwencja w stylu C # spełnia ten wymóg. Jednak nie wszystkie C # jest napisane zgodnie z tą konwencją. Nic nie jest związane z właściwościami per se, które sprawiłyby, że thissłowo kluczowe byłoby niepotrzebne; wywoływany parametr konstruktora xukryje element o nazwie xniezależnie od tego, czy element jest polem, właściwością, czy zdarzeniem.
phoog

246

Nie mam na myśli tego, by zabrzmiało to ponuro, ale to nie ma znaczenia.

Poważnie.

Spójrz na rzeczy, które są ważne: twój projekt, kod, praca, życie osobiste. Żadnemu z nich nie będzie zależeć od tego, czy użyjesz słowa kluczowego „this”, aby zakwalifikować dostęp do pól. To słowo kluczowe nie pomoże Ci wysłać na czas. Nie zmniejszy błędów, nie wpłynie znacząco na jakość kodu ani łatwość konserwacji. To nie zapewni ci podwyżki ani nie pozwoli ci spędzać mniej czasu w biurze.

To naprawdę tylko kwestia stylu. Jeśli podoba Ci się „to”, użyj go. Jeśli nie, to nie rób. Jeśli potrzebujesz go, aby uzyskać poprawną semantykę, użyj go. Prawda jest taka, że ​​każdy programista ma swój unikalny styl programowania. Ten styl odzwierciedla wyobrażenia tego konkretnego programisty o tym, jak powinien wyglądać „najbardziej estetyczny kod”. Z definicji każdy inny programista, który czyta twój kod, będzie miał inny styl programowania. Oznacza to, że zawsze będzie coś, co zrobiłeś, czego drugi facet nie lubi, lub zrobiłby inaczej. W pewnym momencie jakiś facet przeczyta twój kod i narzeka na coś.

Nie martwiłbym się tym. Chciałbym tylko upewnić się, że kod jest tak estetyczny, jak to możliwe, zgodnie z własnymi upodobaniami. Jeśli zapytasz 10 programistów, jak sformatować kod, otrzymasz około 15 różnych opinii. Lepszą rzeczą, na której należy się skupić, jest fakt, że kod jest uwzględniany. Czy rzeczy są abstrakcyjne, prawda? Czy wybrałem sensowne nazwy rzeczy? Czy jest dużo duplikacji kodu? Czy są sposoby na uproszczenie rzeczy? Myślę, że poprawienie tych rzeczy będzie miało największy pozytywny wpływ na Twój projekt, kod, pracę i życie. Zbiegiem okoliczności, prawdopodobnie spowoduje to również, że ten drugi gość narzeka najmniej. Jeśli twój kod działa, jest łatwy do odczytania i dobrze przemyślany, ten drugi facet nie będzie sprawdzał, jak inicjujesz pola. On po prostu użyje twojego kodu, podziwiam jego wielkość,


35
Słowo thiskluczowe ma znaczenie semantyczne. Zobacz komentarz @ JasonBunting poniżej. Mylisz stylistyczne nadużycie thisz jego faktycznym przeznaczeniem. Twoja uwaga jest nie tylko nonszalancka, jest błędna!
Dan Barowy

12
Jeśli masz szansę, możesz ponownie przeczytać moją odpowiedź. Mówię o używaniu go w przypadkach, gdy jest to konieczne do poprawnej semantyki. Możesz także spojrzeć na pytanie o pochodzenie. Pokazuje użycie w przykładach, w których nie jest to konieczne semantycznie. Nie jestem więc pewien, co dokładnie powiedziałem, że to „źle”. Moja odpowiedź z pewnością nie jest nonszalancka.
Scott Wisniewski

9
Czy wiesz jak brzmi twoja odpowiedź? Między wierszami czytam „Jak śmiesz zadawać takie pytanie?” - Moim zdaniem to naprawdę nie jest konstruktywne. Nikt nie wie wszystkiego - dlatego właśnie Stackoverflow: Pomagamy innym i otrzymujemy pomoc. Niektóre tematy znasz, inne znają inne. Pomagajcie sobie nawzajem, nie walczcie ze sobą. Proszę pomyśl o tym.
Matt

9
Nie chcę brzmieć snarky, ale to jedna z najgorszych odpowiedzi. Nie rozumiem, jak przydatne jest porównanie tego z pracą lub życiem osobistym. To, że niektóre rzeczy są mniej ważne niż inne, nie oznacza, że ​​są one nieważne . Spójny styl programowania nie jest nieistotny (przeczytaj książkę na temat czytelności kodu / łatwości konserwacji).
aioobe,

4
Myślę, że mogłeś źle zrozumieć mój punkt widzenia. Nie było tak, że „posiadanie spójnego stylu” jest złe. Nic nie mówię w tym celu. Chodzi o to, że pytanie operacyjne „czy mój przewodnik po stylu powinien tego wymagać”. jako przedrostek dla wszystkich dostępów do pól? ” jest arbitralny i kapryśny.
Scott Wisniewski

96

Używam go tylko wtedy, gdy jest to absolutnie konieczne, tj. Gdy inna zmienna zasłania inną. Tak jak tutaj:

class Vector3
{
    float x;
    float y;
    float z;

    public Vector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

}

Lub, jak wskazuje Ryan Fox, kiedy musisz przekazać to jako parametr. (Zmienne lokalne mają pierwszeństwo przed zmiennymi składowymi)


6
W takim przypadku, dlaczego nie podać innych nazw zmiennych wejściowych konstruktora?
wz366

54

Osobiście staram się zawsze tego używać , odnosząc się do zmiennych składowych. Pomaga wyjaśnić kod i uczynić go bardziej czytelnym. Nawet jeśli nie ma dwuznaczności, ktoś czytający mój kod po raz pierwszy nie wie o tym, ale jeśli zobaczy, że jest on używany konsekwentnie, będzie wiedział, czy patrzy na zmienną składową, czy nie.


9
ale jeśli kiedyś zapomnisz go użyć, będą zdezorientowani
surfuj

2
@surfen, którego można uniknąć dzięki dodatkowym sprawdzeniom stylu, np. w Javie możesz użyć Checkstyle i uruchomić go po pełnej kompilacji (w dowolnym popularnym języku iteracyjnym / OO będą dostępne podobne narzędzia)
Maarten Bodewes

5
@surfen, jakbyś zapomniał o tym w niejednoznacznych przypadkach. Mogę przerwać każdy argument, mówiąc „ale jeśli zapomnisz ...”.
Askolein

6
Wydaje się, że większość ludzi nigdy nie czyta, nie optymalizuje ani nie przepisuje cudzego kodu! Kwalifikatory to oszczędność czasu i motywacji! Bez kwalifikatora to jak magia, jeśli zobaczysz dowolną linię kodu. Więc marnujesz cały czas, tylko sprawdzając, skąd pochodzą te zmienne.
djmj

3
Wiem, że jest to bardzo stary post, ale nie mogę nie skomentować ironii tej odpowiedzi (z którą się zgadzam). W Dżihadzie przeciwko złej notacji węgierskiej każdy, kto odważył się poprzedzić swoje zmienne składowe słowem „m_”, został szybko osypany, ponieważ rozróżnianie zmiennych składowych nie było przydatne ani potrzebne.
Michael J.,

38

Używam go za każdym razem, gdy odwołuję się do zmiennej instancji, nawet jeśli nie muszę. Myślę, że dzięki temu kod jest bardziej przejrzysty.


Chcę rozróżniać zmienne klas tak bardzo, jak tylko mogę, aby kod był bardziej przejrzysty. Kiedyś używałem przedrostka m_ (zmienna członkowska) np. Prywatny ciąg m_name. Teraz używam tego np. Jeśli mam klasę Test {prywatny ciąg a; public someMethod () {this.a = "foo"; }}
Internet szerokopasmowy

36

Nie mogę uwierzyć, że wszyscy ludzie, którzy twierdzą, że używanie go zawsze jest „najlepszą praktyką” i tak dalej.

Używaj „tego”, gdy występuje dwuznaczność, jak w przykładzie Coreya lub gdy musisz przekazać obiekt jako parametr, jak w przykładzie Ryana . Nie ma powodu, aby używać go inaczej, ponieważ możliwość rozwiązania zmiennej opartej na łańcuchu zasięgu powinna być wystarczająco jasna, aby kwalifikujące się do niej zmienne były niepotrzebne.

EDYCJA: Dokumentacja C # na „to” wskazuje jeszcze jedno użycie, oprócz dwóch wymienionych powyżej, dla słowa kluczowego „to” - do deklarowania indeksatorów

EDYCJA: @Juan: Huh, nie widzę żadnej niespójności w moich wypowiedziach - istnieją 3 przypadki, w których użyłbym słowa kluczowego „this” (jak udokumentowano w dokumentacji C #), i są takie chwile, kiedy naprawdę tego potrzebujesz . Trzymanie „tego” przed zmiennymi w konstruktorze, gdy nie ma cieniowania, jest po prostu stratą naciśnięć klawiszy i stratą czasu podczas czytania, nie przynosi żadnych korzyści.


21
@ JasonBunting : Nie możesz czasem zrobić czegoś, a nie innych ... to jest mylące ... Mam nadzieję, że nigdy nie pracuję w twoim kodzie Nie zawsze możesz założyć, że osoba, która czyta twój kod w przyszłości, zrozumie co scenariusza, trzeba być jak najdalej, a jednym ze sposobów, aby to osiągnąć jest spójne
juan

@juan, 10 lat później. Nadal uważasz, że używanie „tego” jest dobrą praktyką? :)
Scott Adams,

2
@ScottAdams Nadal wierzę w spójności i jasności, tak
juan

A co z określeniem zakresu zmiennej (lokalnej lub członkowskiej) tylko na podstawie jej spojrzenia? Czy „to” nie jest uzasadnione w tym celu? A może chcesz powiedzieć, że jeśli napiszemy mniejsze metody, to i tak łatwo będzie zrozumieć zakres zmiennej?
BornToCode

27

Używam go, ilekroć StyleCop mi to nakazuje. StyleCop musi być przestrzegane. O tak.


1
A ReSharper mówi mi, żebym go nie używał. Trochę mylące, gdy jednocześnie używam StyleCop i ReSharper :) Ale przechylam się do odpowiedzi Coreys powyżej, aby użyć tego słowa kluczowego tylko wtedy, gdy jest to absolutnie konieczne.
Gunnar

@Gunnar, istnieje opcja wyłączenia pozbywania się zbędnych „tego”. w R #
Winger Sendon

@EmperorAiman ​​- Tak, wiem. Chodzi mi o to, że te dwa popularne narzędzia do formatowania są domyślnie, co sugeruje dwie różne rzeczy i może to być mylące. „Być albo nie być ...” :)
Gunnar,

11

Za każdym razem, gdy potrzebujesz odwołania do bieżącego obiektu.

Jednym szczególnie przydatnym scenariuszem jest wywołanie funkcji przez obiekt i jego przekazanie.

Przykład:

void onChange()
{
    screen.draw(this);
}

7

Zwykle używam go również wszędzie, aby upewnić się, że jasne jest, że mamy do czynienia z członkami instancji.


5

Używam go wszędzie tam, gdzie może być niejednoznaczność (oczywiście). Nie tylko niejednoznaczność kompilatora (w takim przypadku byłaby wymagana), ale także niejednoznaczność dla kogoś, kto patrzy na kod.


5

Innym dość rzadkim zastosowaniem tego słowa kluczowego jest wywołanie jawnej implementacji interfejsu z klasy implementującej. Oto wymyślony przykład:

class Example : ICloneable
{
    private void CallClone()
    {
        object clone = ((ICloneable)this).Clone();
    }

    object ICloneable.Clone()
    {
        throw new NotImplementedException();
    }
}

4

Oto kiedy go używam:

  • Dostęp do metod prywatnych z poziomu klasy (w celu odróżnienia)
  • Przekazywanie bieżącego obiektu do innej metody (lub jako obiekt nadawcy, w przypadku zdarzenia)
  • Podczas tworzenia metod rozszerzenia: D

Nie używam tego w polach prywatnych, ponieważ poprzedzam nazwy zmiennych pól prywatnych znakiem podkreślenia (_).


4

[C ++]

Zgadzam się z brygadą „wykorzystaj, kiedy będziesz musiał”. Niepotrzebne dekorowanie kodu za pomocą tego nie jest świetnym pomysłem, ponieważ kompilator nie ostrzeże Cię, gdy o tym zapomnisz. Wprowadza to potencjalne zamieszanie dla osób, które oczekują, że zawsze tam będzie, tzn. Będą musiały o tym pomyśleć .

Kiedy go użyjesz? Właśnie rozejrzałem się wokół losowego kodu i znalazłem te przykłady (nie oceniam, czy są to dobre rzeczy do zrobienia, czy nie):

  • Przekazywanie „siebie” do funkcji.
  • Przypisywanie „siebie” do wskaźnika lub czegoś w tym rodzaju.
  • Odlewanie, tj. Odlewanie w górę / w dół (bezpieczne lub w inny sposób), odlewanie ciągłości itp.
  • Kompilator wymusił ujednoznacznienie.

3

Zawsze powinieneś go używać, używam go do rozróżniania prywatnych pól i parametrów (ponieważ nasze konwencje nazewnictwa stanowią, że nie używamy prefiksów dla nazw członków i parametrów (i są oparte na informacjach znalezionych w Internecie, więc uważam, że najlepsze praktyki))


3

Używam go, gdy w funkcji, która akceptuje odwołanie do obiektu tego samego typu, chcę wyraźnie wyjaśnić, do którego obiektu się odwołuję, gdzie.

Na przykład

class AABB
{
  // ... members
  bool intersects( AABB other )
  {
    return other.left() < this->right() &&
           this->left() < other.right() &&

           // +y increases going down
           other.top() < this->bottom() &&
           this->top() < other.bottom() ;
  }
} ;

(vs)

class AABB
{
  bool intersects( AABB other )
  {
    return other.left() < right() &&
           left() < other.right() &&

           // +y increases going down
           other.top() < bottom() &&
           top() < other.bottom() ;
  }
} ;

Na pierwszy rzut oka, do którego right()odnosi się AABB ? thisDodaje trochę osadnika.


3

W odpowiedzi Jakuba Šturca jego nr 5 na temat przekazywania danych między wykonawcami prawdopodobnie można by wyjaśnić. Dotyczy to przeciążania konstruktorów i jest to jedyny przypadek, w którym użycie thisjest obowiązkowe. W poniższym przykładzie możemy wywołać sparametryzowany konstruktor z konstruktora bez parametrów z parametrem domyślnym.

class MyClass {
    private int _x
    public MyClass() : this(5) {}
    public MyClass(int v) { _x = v;}
}

Okazało się, że jest to szczególnie przydatna funkcja przy okazji.


2

Przyzwyczaiłem się używać go swobodnie w Visual C ++, ponieważ spowodowałoby to uruchomienie IntelliSense. Nacisnąłem klawisz „>” i jestem leniwy. (i podatne na literówki)

Ale nadal go używam, ponieważ uważam, że przydaje się, że wywołuję funkcję członka zamiast funkcji globalnej.


1

Zazwyczaj podkreślam pola znakiem _, więc tak naprawdę nigdy nie muszę tego używać. R # i tak ma tendencję do ich refaktoryzacji ...


1

Prawie używam tego tylko przy odwoływaniu się do właściwości type z tego samego typu. Jako inny użytkownik wspomniano, ja też podkreślić lokalnych pól więc są widoczne bez potrzeby tego .


1

Używam go tylko wtedy, gdy jest to wymagane, z wyjątkiem operacji symetrycznych, które ze względu na polimorfizm pojedynczego argumentu muszą być zastosowane w metodach jednej strony:

boolean sameValue (SomeNum other) {
   return this.importantValue == other.importantValue;
} 

1

[C ++]

ten jest stosowany w operatorze przypisania, gdzie przez większość czasu trzeba sprawdzić i zapobiec dziwne (niezamierzone, niebezpieczne, lub tylko strata czasu dla programu) takie rzeczy jak:

A a;
a = a;

Twój operator przydziału zostanie napisany:

A& A::operator=(const A& a) {
    if (this == &a) return *this;

    // we know both sides of the = operator are different, do something...

    return *this;
}

1

this na kompilatorze C ++

Kompilator C ++ po cichu wyszuka symbol, jeśli nie znajdzie go natychmiast. Czasami dobrze jest:

  • używając metody klasy macierzystej, jeśli nie przeładowałeś jej w klasie potomnej.
  • promowanie wartości typu na inny typ

Ale czasami po prostu nie chcesz zgadywać kompilatora. Chcesz, aby kompilator wybrał odpowiedni symbol, a nie inny.

Dla mnie są to czasy, kiedy w ramach metody chcę uzyskać dostęp do metody elementu lub zmiennej elementu. Po prostu nie chcę, żeby jakiś losowy symbol został odebrany tylko dlatego, że napisałem printfzamiast print. this->printfnie skompilowałbym.

Chodzi o to, że w starszych bibliotekach C (§), starszym kodzie napisanym przed laty (§§) lub czymkolwiek innym, co mogłoby się zdarzyć w języku, w którym kopiowanie / wklejanie jest przestarzałą, ale wciąż aktywną funkcją, czasami informującą kompilator, aby nie odtwarzał spryt to świetny pomysł.

Z tych powodów korzystam this.

(§) nadal jest to dla mnie pewnego rodzaju tajemnica, ale teraz zastanawiam się, czy to, że umieściłeś nagłówek <windows.h> w swoim źródle, jest przyczyną, dla której wszystkie starsze symbole bibliotek C zanieczyszczą twoją globalną przestrzeń nazw

(§§) Zdając sobie sprawę, że „musisz dołączyć nagłówek, ale włączenie tego nagłówka spowoduje uszkodzenie kodu, ponieważ używa on głupiego makra o nazwie ogólnej” to jeden z tych momentów w rosyjskiej ruletce życia programisty


1

'to.' pomaga znaleźć członków w tej klasie z dużą liczbą członków (zwykle z powodu głębokiego łańcucha dziedziczenia).

Wciśnięcie CTRL + spacja nie pomaga w tym, ponieważ zawiera także typy; gdzie-jako „to”. obejmuje TYLKO członków.

Zwykle usuwam go, gdy mam to, czego szukałem: ale to tylko mój styl.

Jeśli chodzi o styl, jeśli jesteś samotnym tropicielem - decydujesz; jeśli pracujesz dla firmy, trzymaj się zasad firmy (spójrz na rzeczy w kontroli źródła i zobacz, co robią inni). Jeśli chodzi o wykorzystanie go do zakwalifikowania członków, nie jest to ani dobre, ani złe. Jedyną złą rzeczą jest niespójność - oto złota zasada stylu. Zostaw zbieranie nitów innym. Zamiast tego poświęć czas na zastanawianie się nad prawdziwymi problemami z kodowaniem - i oczywiście z kodowaniem.


1

Używam go za każdym razem, gdy mogę. Uważam, że dzięki temu kod jest bardziej czytelny, a bardziej czytelny kod oznacza mniej błędów i większą łatwość konserwacji.


1

Jeśli jest wielu programistów pracujących na tej samej podstawie kodu, potrzebne są pewne wytyczne / reguły kodu. Tam, gdzie pracuję, postanowiliśmy używać „tego” na polach, właściwościach i zdarzeniach.

Dla mnie sensowne jest zrobienie tego w ten sposób, ułatwia to odczytanie kodu, gdy rozróżniasz zmienne klasowe i zmienne metodyczne.


0

To zależy od standardu kodowania, nad którym pracuję. Jeśli używamy _ do oznaczenia zmiennej instancji, wówczas „to” staje się zbędne. Jeśli nie używamy _, to zwykle używam tego do oznaczenia zmiennej instancji.


0

Używam go do wywoływania Intellisense, podobnie jak JohnMcG , ale wrócę i wyczyszczę „this->”, kiedy skończę. Postępuję zgodnie z konwencją Microsoftu polegającą na dodawaniu zmiennych składowych członu do „m_”, więc pozostawienie go jako dokumentacji byłoby zbędne.


0

1 - Typowy idiom ustawiający Java:

 public void setFoo(int foo) {
     this.foo = foo;
 }

2 - Podczas wywoływania funkcji z tym obiektem jako parametrem

notifier.addListener(this);

0

Jest jedno zastosowanie, o którym jeszcze nie wspomniano w C ++, i które nie ma na celu odwoływania się do własnego obiektu ani ujednoznaczniania członka z otrzymanej zmiennej.

Można użyć thisdo przekształcenia nieuzależnionej nazwy na nazwę zależną od argumentu w klasach szablonów, które dziedziczą z innych szablonów.

template <typename T>
struct base {
   void f() {}
};

template <typename T>
struct derived : public base<T>
{
   void test() {
      //f(); // [1] error
      base<T>::f(); // quite verbose if there is more than one argument, but valid
      this->f(); // f is now an argument dependent symbol
   }
}

Szablony są kompilowane za pomocą mechanizmu dwuprzebiegowego. Podczas pierwszego przejścia rozpoznawane i sprawdzane są tylko nazwy nie-zależne od argumentów, podczas gdy nazwy zależne są sprawdzane tylko pod kątem spójności, bez faktycznego zastępowania argumentów szablonu.

Na tym etapie, bez faktycznego podstawiania typu, kompilator nie ma prawie żadnych informacji o tym, co base<T>mogłoby być (zauważ, że specjalizacja szablonu podstawowego może przekształcić go w zupełnie inne typy, nawet typy nieokreślone), więc po prostu zakłada, że ​​jest to typ . Na tym etapie niezależne wywołanie, fktóre wydaje się programiście naturalne, jest symbolem, który kompilator musi znaleźć jako element derivedlub w przestrzeniach nazw - co nie zdarza się w tym przykładzie - i narzeka.

Rozwiązaniem jest przekształcenie nazwy fniezależnej w nazwę zależną. Można to zrobić na kilka sposobów, jednoznacznie wskazując typ, w którym jest on zaimplementowany (- base<T>::fdodanie base<T>powoduje, że symbol jest zależny, Ta kompilator po prostu przyjmie, że istnieje, i opóźni faktyczne sprawdzenie drugiego przejścia, po podstawianie argumentów.

Drugim sposobem, dużo sortującym, jeśli dziedziczysz po szablonach, które mają więcej niż jeden argument lub długie nazwy, jest po prostu dodanie this->przed symbolem. Ponieważ implementowana klasa szablonów zależy od argumentu (dziedziczy po base<T>) this->jest zależna od argumentu i otrzymujemy ten sam wynik: this->fjest sprawdzany w drugiej rundzie, po podstawieniu parametru szablonu.


-2

Nie powinieneś używać „tego”, chyba że absolutnie musisz.

Istnieje kara związana z niepotrzebną gadatliwością. Powinieneś dążyć do tego, aby kod był dokładnie tak długi, jak powinien, i już nie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.