Troufám si tvrdit, že většina programátorů o klíčovém slovu this
slyšela a ví, že se jedná o automaticky zpřístupněný ukazatel v metodě, který ukazuje na objekt, na kterém byla metoda zavolána. Obvykle se s tímto klíčovým slovem nesetkáte, protože když v metodě voláte jiné metody či přistupujete na datové složky objektu, tak je onen ukazatel implicitní. Jsou ovšem situace, ve kterých je použití tohoto klíčového slova nutné. A o těchto situacích bude následující příspěvek.
Co je to klíčové slovo this
?
Klíčové slovo this
lze v C++ použít v definicích metod, kde slouží k přístupu k objektu, na kterém byla metoda zavolána. Dá se na něj dívat jako na nultý parametr, který se automaticky předává všem volaným metodám. Pokud by tato podpora v C++ chyběla, museli byste si ukazatel na objekt předávat sami, což by značně znepřehlednilo kód. Typem this
je ukazatel na aktuální objekt (či konstantní/volatile ukazatel, pokud se jedná o konstantní/volatile metodu).
Hlavní důvod, proč se s tímto klíčovým slovem příliš nesetkáváte, je ten, že jeho použití je mnohdy pouze volitelné. Skutečně, pokud v metodě voláte jinou metodu či přistupujete k datové složce, tak za vás volání přes this
vyřeší překladač. To nás přivádí k následující otázce.
Kdy je potřeba jej použít?
Existují situace, ve kterých klíčové slovo this
použít musíte. Zde je seznam některých z nich.
(1) Potřebujete v metodě někam předat ukazatel na objekt, na kterém byla metoda zavolána
Často se to používá při implementaci návrhového vzoru Visitor. Příklad:
class AddExpr { public: // ... void accept(Visitor *v) { v->visit(this); } }
Jako kuriozitu tu pak máme harakiri ve stylu C++ :).
delete this;
Pokud by vás zajímalo využití, tak mrkněte zde. Zde je pak k dispozici seznam věcí, na které si musíte dát při použití této konstrukce pozor.
(2) Potřebujete v metodě někam předat objekt, na kterém byla metoda zavolána
Toto využití this
vídáme v implementacích operátoru přiřazení, který vrací referenci na objekt, do kterého se přiřazuje. Níže je ukázka implementace tohoto operátoru pomocí copy & swap idiomu.
T & operator=(T o) { // T zde musí být předáno hodnotou swap(*this, o); return *this; }
(3) Existuje proměnná se stejným názvem jako datová složka
V následujícím kódu je použití this
nutné.
class Wrapper { public: void wrap(int width) { this->width = width; // .. } private: int width; };
Bez něj by totiž došlo k přiřazení parametru do sebe sama. Klíčové slovo this
zde slouží k rozlišení, zda se přistupuje k parametru funkce či k datové složce objektu. Obdobný problém nastává v případě kolizí názvů lokálních proměnných a metod.
Pokud se však v této situaci jedná o inicializační část konstruktoru, pak this
použít nemusíte:
class MyNum { public: MyNum(int value, int bitWidth): value(value), bitWidth(bitWidth) { // .. } private: int value; int bitWidth; };
Překladač se automaticky postará o to, aby kód dělal přesně to, co očekáváte, čili nainicializoval datové složky pomocí hodnot parametrů.
(4) Voláte v podtřídě metodu z šablonové nadtřídy
Kvůli způsobu vyhledávání jmen (name lookup) v C++ musíte v následujícím příkladu před voláním f()
v podtřídě použít this
.
template <typename T> class A { protected: void f() { // ... } }; template <typename T> class B: A<T> { public: void g() { this->f(); // zde musí být this-> } };
V opačném případě vám bude překladač hlásit chybu (poznámka: starší verze gcc chybu v tomto případě nehlásily).
Pokud by vás zajímaly detaily, tak mrkněte např. zde. Obdobná situace nastává v případě, když přistupujete k členské proměnné z nadtřídy, která je šablona. Související odkaz na FAQ je zde (je tam uveden i způsob, jak toto vyřešit bez použití this
).
Je to vše?
Seznam výše zřejmě nebude vyčerpávající. Pokud víte o nějaké další situaci, ve které je třeba klíčové slovo this
použít, nezapomeňte se podělit v komentáři!