Kapan saya harus menulis secara eksplisit this->member
dalam metode kelas?
research.att.com/~bs/
sekarang stroustrup.com
. Tautan baru: stroustrup.com/bs_faq2.html#this
Kapan saya harus menulis secara eksplisit this->member
dalam metode kelas?
research.att.com/~bs/
sekarang stroustrup.com
. Tautan baru: stroustrup.com/bs_faq2.html#this
Jawaban:
Biasanya, Anda tidak harus, this->
tersirat.
Terkadang, ada ambiguitas nama, yang dapat digunakan untuk membedakan anggota kelas dan variabel lokal. Namun, ini adalah kasus yang sama sekali berbeda this->
yang secara eksplisit diperlukan.
Perhatikan kode berikut:
template<class T>
struct A {
int i;
};
template<class T>
struct B : A<T> {
int foo() {
return this->i;
}
};
int main() {
B<int> b;
b.foo();
}
Jika Anda mengabaikannya this->
, kompilator tidak akan tahu bagaimana memperlakukannya i
, karena mungkin ada atau mungkin tidak ada di semua contoh A
. Untuk memberitahunya bahwa i
memang anggota dari A<T>
, untuk apapun T
, this->
prefiks diperlukan.
Catatan: Anda masih bisa menghilangkan this->
prefiks dengan menggunakan:
template<class T>
struct B : A<T> {
using A<T>::i; // explicitly refer to a variable in the base class
int foo() {
return i; // i is now known to exist
}
};
i
tidak ada di A
. Bisakah saya mendapatkan contoh?
template<> struct A<float> { float x; };
Jika Anda mendeklarasikan variabel lokal dalam metode dengan nama yang sama sebagai anggota yang sudah ada, Anda harus menggunakan this-> var untuk mengakses anggota kelas alih-alih variabel lokal.
#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
cetakan:
5
4
Ada beberapa alasan mengapa Anda mungkin perlu menggunakan this
pointer secara eksplisit.
Meskipun saya biasanya tidak terlalu menyukainya, saya pernah melihat orang lain menggunakan ini-> hanya untuk mendapatkan bantuan dari Intellisense!
Beberapa standar pengkodean menggunakan pendekatan (2) karena mereka mengklaim itu membuat kode lebih mudah dibaca.
Contoh:
Asumsikan MyClass memiliki variabel anggota yang disebut 'count'
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
Ada beberapa kasus di mana penggunaan this
harus digunakan, dan ada kasus lain di mana menggunakan this
penunjuk adalah salah satu cara untuk menyelesaikan masalah.
1) Alternatif Tersedia : Untuk menyelesaikan ambiguitas antara variabel lokal dan anggota kelas, seperti yang diilustrasikan oleh @ASk .
2) Tidak Ada Alternatif: Untuk mengembalikan pointer atau referensi ke this
dari fungsi anggota. Hal ini sering dilakukan (dan harus dilakukan) ketika overloading operator+
, operator-
, operator=
, dll:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
Melakukan ini mengizinkan idiom yang dikenal sebagai " method chaining ", di mana Anda melakukan beberapa operasi pada suatu objek dalam satu baris kode. Seperti:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Beberapa menganggap ini konseptual, yang lain menganggapnya sebagai kekejian. Hitung saya di kelompok terakhir.
3) Tidak Ada Alternatif: Untuk menyelesaikan nama dalam tipe dependen. Ini muncul saat menggunakan template, seperti dalam contoh ini:
#include <iostream>
template <typename Val>
class ValHolder
{
private:
Val mVal;
public:
ValHolder (const Val& val)
:
mVal (val)
{
}
Val& GetVal() { return mVal; }
};
template <typename Val>
class ValProcessor
:
public ValHolder <Val>
{
public:
ValProcessor (const Val& val)
:
ValHolder <Val> (val)
{
}
Val ComputeValue()
{
// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
return ret;
}
};
int main()
{
ValProcessor <int> proc (42);
const int val = proc.ComputeValue();
std::cout << val << "\n";
}
4) Alternatif yang Tersedia: Sebagai bagian dari gaya pengkodean, untuk mendokumentasikan variabel mana yang merupakan variabel anggota dan bukan variabel lokal. Saya lebih suka skema penamaan yang berbeda di mana anggota varibales tidak pernah bisa memiliki nama yang sama dengan penduduk setempat. Saat ini saya menggunakan mName
untuk anggota dan name
penduduk setempat.
Satu kasus lainnya adalah saat memanggil operator. Misalnya, bukan
bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
bisa dibilang
bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
Yang mungkin lebih mudah dibaca. Contoh lainnya adalah copy-and-swap:
Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
Saya tidak tahu mengapa itu tidak tertulis swap(temp)
tetapi ini tampaknya umum.
const
fungsi anggota pada sementara ( Type(rhs).swap(*this);
legal dan benar) tapi kaleng sementara tidak mengikat parameter referensi non-const (menolak compiler swap(Type(rhs));
serta this->swap(Type(rhs));
)
Anda hanya perlu menggunakan this-> jika Anda memiliki simbol dengan nama yang sama di dua ruang nama potensial. Ambil contoh:
class A {
public:
void setMyVar(int);
void doStuff();
private:
int myVar;
}
void A::setMyVar(int myVar)
{
this->myVar = myVar; // <- Interesting point in the code
}
void A::doStuff()
{
int myVar = ::calculateSomething();
this->myVar = myVar; // <- Interesting point in the code
}
Pada poin-poin menarik dalam kode, mengacu pada myVar akan mengacu pada myVar (parameter atau variabel) lokal. Untuk mengakses anggota kelas yang juga disebut myVar, Anda perlu menggunakan "this->" secara eksplisit.
this->
yang sepele untuk dihindari (berikan nama variabel lokal yang berbeda). Semua kegunaan yang sangat menarik this
bahkan tidak disebutkan oleh jawaban ini.
Kegunaan lain untuk ini (seperti yang saya pikirkan ketika saya membaca ringkasan dan setengah pertanyaan ....), mengabaikan disambiguasi penamaan (buruk) di jawaban lain, adalah jika Anda ingin mentransmisikan objek saat ini, mengikatnya dalam objek fungsi atau gunakan dengan pointer-to-member.
void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
Semoga membantu untuk menunjukkan kegunaan lain selain ini-> anggota.
Anda perlu menggunakan this
untuk membedakan antara parameter / variabel lokal dan variabel anggota.
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
Tujuan utama (atau saya dapat mengatakan, satu-satunya) tujuan dari this
pointer adalah menunjuk ke objek yang digunakan untuk memanggil fungsi anggota.
Berdasarkan tujuan ini, kita dapat memiliki beberapa kasus yang hanya menggunakan this
penunjuk yang dapat menyelesaikan masalah.
Misalnya, kita harus mengembalikan objek pemanggilan dalam fungsi anggota dengan argumen objek kelas yang sama:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
Saya menemukan kasus menarik lainnya dari penggunaan eksplisit pointer "ini" dalam buku Effective C ++.
Misalnya, Anda memiliki fungsi seperti konstanta
unsigned String::length() const
Anda tidak ingin menghitung panjang String untuk setiap panggilan, karena itu Anda ingin men-cache-nya dengan melakukan sesuatu seperti
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
Tapi ini tidak bisa dikompilasi - Anda mengubah objek dalam fungsi const.
Trik untuk mengatasi ini membutuhkan casting ini ke non-const ini :
String* const nonConstThis = (String* const) this;
Kemudian, Anda dapat melakukannya di atas
nonConstThis->lengthInitialized = 1;
length
mutable, atau bahkan meletakkannya di struct bersarang. Menghilangkan keteguhan hampir tidak pernah merupakan ide yang bagus.
const
fungsi anggota, itu harus mutable
. Jika tidak, Anda membuat hidup lebih rumit untuk Anda sebagai pengelola lainnya.