C++ Dilinde this pointer .!!
- Yusuf Hançar
- May 30, 2023
- 4 min read
Bir önceki class yazısında ucundan değindiğimiz this pointer konusunu ele alacağız. C++ dilinde sınıf içerisindeki static olmayan(non-static) üye fonksiyonların gizli bir sınıf türünden parametresi olduğuna değinmiştik. this pointer anahtar sözcüğü de sadece sınıfın non-static üye elemanları(data members) için kullanılmaktadır. C++ dilinin kuralları gereği de this ifadesi PR(pure R value) value expression olarak kategorize edilmektedir. Değerini gösteren *this ifadesi ise L value expression olarak ele alınmaktadır.
Yani this işaretçisi(pointer) o anda işlem gören nesneye işaret etmektedir. Sınıfın non-static veri elemanları ve fonksiyonlarına erişim için kullanılmaktadır. Aşağıda this işaretçisinin ne işe yaradığı ve kullanımının gerekli olduğu durumları örneklendirerek anlamaya çalışalım :
class ThisClass {
public :
void smart_code();
};
int glob_func()
{
this;
}
*****************************
AÇIKLAMA: global olan glob_func() fonksiyonu içerisindeki this çağrısı syntax error.
*****************************
class ThisClass {
public :
void smart_code();
};
void ThisClass::smart_code()
{
this;
*this
}
*****************************
AÇIKLAMA: this çağrısı smart_code fonksiyonu hangi nesne için çağırılırsa o nesnenin adresidir. *this ilgili adresteki nesneye erişim için kullanımdır.
!!java dilinde this adresi değil hangi nesne için çağırılırsa o nesnenin kendisini ifade eder.
*****************************
class ThisClass {
private :
int sc;
public :
void smart_code();
};
void ThisClass::smart_code()
{
sc = 3;
this->sc = 4;
(*this).sc = 5;
ThisClass::sc = 6;
}
*****************************
AÇIKLAMA: this pointer kullanılarak çağırılan nesneye erişim ve değer atama ile ilgili örnekler verilmektedir.
*İlk atama işleminde veri elemanına direkt erişim söz konusudur.
*İkinci atamada ise -> operatoru ile yapılan sonraki atama da this işaretçisi kullanılarak veri elemanına erişim söz konusudur.
*Sonraki ise this pointer işaret edilen nesnenin veri elemanına erişim için kullanılır.
*Sonuncu da ise sınıf adı ile :: operatoru ile nitelenerek erişim söz konusudur.
*****************************
class ThisClass {
public :
void smart_code();
void this_func();
};
void ThisClass::smart_code()
{
cout << "smart_code işlevi çağrısı." << endl;
cout << "this : " << this << endl;
this_func();
}
void ThisClass::this_func()
{
cout << "this_func işlevi çağrısı." << endl;
cout << "this : " << this << endl;
}
int main()
{
ThisClass sc;
cout << "&sc : " << &sc << endl;
sc.smart_code();
}
*****************************
AÇIKLAMA: this nesnesi ile ThisClass sınıfından oluşturulan sc nesnesinin adresleri aynı olacaktır. Çünkü hangi nesne için çağırılırsa onun adresidir demiştik.
*****************************
class ThisClass {
public :
void smart_code();
};
void th_func(ThisClass* th)
{
cout << "global th_func() çağrısı. " << th << endl;
}
void ThisClass::smart_code()
{
cout << "smart_code() çağrısı." << this << endl;
th_func(this);
}
int main()
{
ThisClass sc;
cout << "&sc : " << &sc << endl;
sc.smart_code();
}
*****************************
AÇIKLAMA: smart_code() fonksiyonu içerisinde maindeki ThisClass sınıfı türünden oluşturulan sc nesnesi için yapılan çağrı bu nesnesin adresi ile global th_func() fonksiyonuna çağrı yapılmıştır. Bunun içinde adresini kullanmaktadır.
*****************************
class ThisClass {
public :
void smart_code();
};
void th_func(ThisClass& th)
{
cout << "global th_func() çağrısı. " << th << endl;
}
void ThisClass::smart_code()
{
cout << "smart_code() çağrısı." << this << endl;
th_func(*this);
}
int main()
{
ThisClass sc;
cout << "&sc : " << &sc << endl;
sc.smart_code();
}
*****************************
AÇIKLAMA: üstteki pointer ile yapılan örneğin reference semantik ile kullanımıdır ve sık sık kullanım ihtiyacı duyulan bir durumdur.
*****************************
Bir non-static data member hangi nesne için çağırılmış ise o nesnenin adresini;
Bir pointer değişkene geçecekse(global bir fonksiyonu bu adres ile çağıracak ise),
Reference semantik ile global bir fonksiyona geçecek ise this pointer kullanmak zorundadır.
ThisClass* ptr_smart_code();
ThisClass& ref_smart_code();
*****************************
AÇIKLAMA: Sınıfın non-static üye fonksiyonlarının sınıf türünden adres ya da referans döndürdükleri durumlarda da this kullanılmaktadır. Bu durumun kullanım nedeni de; çağırıldığı nesnenin adresi ya da nesnenin kendisini döndürmesidir.
*****************************
// thisclass.h
class ThisClass {
public :
ThisClass* ptr_smart_code();
ThisClass& ref_smart_code();
};
*******************************************************************
// thisclass.cpp
ThisClass* ThisClass::ptr_smart_code()
{
return this;
}
ThisClass& ThisClass::ref_smart_code()
{
return *this;
}
int main()
{
ThisClass sc;
sc.ptr_smart_code();
sc.ref_smart_code();
}
*****************************
AÇIKLAMA: ptr_smart_code() fonksiyonunun geri dönüş değeri; bu fonksiyona yapılan çağrı yapan nesnenin adresidir.
* sc.ptr_smart_code(); ifadesi sc nesnesinin adresine eşittir.
* sc.ref_smart_code(); ifadesi sc nesnesinin kendisine eşittir. Hem ref_smart_code fonksiyonuna çağrı yapılır hem de sc nesnesi elde edilir.
*****************************
// thisclass.h
class ThisClass {
public :
ThisClass& smart_code1();
ThisClass& smart_code2();
ThisClass& smart_code3();
};
*******************************************************************
// thisclass.cpp
ThisClass& ThisClass::smart_code1()
{
return *this;
}
ThisClass& ThisClass::smart_code2()
{
return *this;
}
ThisClass& ThisClass::smart_code3()
{
return *this;
}
int main()
{
ThisClass sc;
sc.smart_code1().smart_code2().smart_code3();
return 0;
}
*****************************
AÇIKLAMA: Tanımlanan üç fonksiyonda *this döndürüyor.
C# ve java gibi dillerde bu çağrılara fluent API denir.
*****************************
int main()
{
int val = 5;
double dval = 2.7;
bool bval = true;
cout << val << dval << bval << endl;
}
*****************************
AÇIKLAMA: buradaki çağrılarda cout << çağrısının geçerli olmasının nedeni derleyici sınıfın bir üye fonksiyonuna çağrıya dönüştürmektedir. Yani operator overloading ile geçerli kılınmaktadır. Olmasaydı eğer cout.operator<<(val) şeklinde yazmak zorunda kalırdık. Sınıfın üye fonksiyon çağrısı *this döndürmektedir. *this cout nesnesinin kendisidir.
*****************************
class ThisClass {
public :
void smart_code();
void const_func()const;
};
ThisClass glob_val;
void ThisClass::smart_code()
{
*this = glob_val; // legal
}
void ThisClass::const_func()const
{
// *this const ve const nesneye atama yapılamayağı için syntax error.
*this = glob_val;
}
class ThisClass {
public :
ThisClass* f1();
ThisClass& f2();
ThisClass* f3()const;
ThisClass& f4()const;
};
ThisClass* ThisClass::f1() // bunun gizli parametresi de ThisClass*
{
return this; // ThisClass* ------------ ThisClass*
}
ThisClass& ThisClass::f2() // bunun gizli parametresi de ThisClass*
{
return *this; // ThisClass* ------------ ThisClass*
}
ThisClass* ThisClass::f3()const // bunun gizli parametresi de ThisClass*
{
return this; // const ThisClass* ----- ThisClass* // syntax error.
}
ThisClass& ThisClass::f4()const // bunun gizli parametresi de ThisClass*
{
return *this; // const ThisClass* ---- ThisClass* // syntax error.
}
class ThisClass {
public :
const ThisClass* f1()const;
const ThisClass& f2()const;
};
const ThisClass* ThisClass::f1()const
{
return this; //legal
}
const ThisClass& ThisClass::f2()const
{
return *this; // legal
}
class ThisClass {
public :
void smart_code();
};
ThisClass glob_val;
void ThisClass::smart_code()
{
this = &glob_val;
}
*****************************
AÇIKLAMA: this kendisi her zaman const ve PR value olduğu için atama sentaks hatasıdır.
*****************************
class ThisClass {
public :
void smart_code1();
//void smart_code1(ThisClass* const this);
void smart_code2()const;
//void smart_code2(const ThisClass* const this);
};
*****************************
AÇIKLAMA:
*this pointer kendisi top level const. kendisini değiştiremeyiz.
*const üye fonksiyonlar için ise low level const ve gösterdiği nesneyi değiştiremeyiz.
*****************************
Comments