Bir this->member
sınıfın yöntemini açıkça ne zaman yazmalıyım ?
research.att.com/~bs/
şimdi öyle görünüyor stroustrup.com
. Yeni bağlantı: stroustrup.com/bs_faq2.html#this
Bir this->member
sınıfın yöntemini açıkça ne zaman yazmalıyım ?
research.att.com/~bs/
şimdi öyle görünüyor stroustrup.com
. Yeni bağlantı: stroustrup.com/bs_faq2.html#this
Yanıtlar:
Genellikle buna gerek yoktur this->
, ima edilir.
Bazen, sınıf üyelerini ve yerel değişkenleri netleştirmek için kullanılabilecek bir ad belirsizliği vardır. Ancak, burada this->
açıkça gerekli olan tamamen farklı bir durum var .
Aşağıdaki kodu göz önünde bulundurun:
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();
}
Atlarsanız this->
, derleyici, i
tüm örneklerinde mevcut olabileceği veya bulunmayabileceği için nasıl davranılacağını bilmez A
. i
Gerçekten de üyesi olduğunu söylemek için A<T>
, herhangi biri T
için this->
ön ek gereklidir.
Not: Aşağıdakileri this->
kullanarak öneki atlamak yine de mümkündür :
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
mevcut olmayabilir A
. Bir örnek alabilir miyim?
template<> struct A<float> { float x; };
Bir yöntemde mevcut bir üye ile aynı ada sahip bir yerel değişken bildirirseniz, sınıf üyesine yerel değişken yerine erişmek için this-> var'ı kullanmanız gerekecektir.
#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();
}
baskılar:
5
4
this
İşaretçiyi açık bir şekilde kullanmanız gerekmesinin birkaç nedeni vardır .
Genelde hoşuma gitmese de, başkalarının bunu sadece intellisense'den yardım almak için kullandığını gördüm!
Bazı kodlama standartları, kodun okunmasını kolaylaştırdığını iddia ettikleri için yaklaşım (2) kullanır.
Örnek:
MyClass'ın 'count' adında bir üye değişkeni olduğunu varsayın
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
Kullanmanın kullanılması this
gereken birkaç durum vardır ve this
imleci kullanmanın bir sorunu çözmenin bir yolu olduğu başka durumlar da vardır .
1) Mevcut Alternatifler : @ASk ile gösterildiği gibi yerel değişkenler ve sınıf üyeleri arasındaki belirsizliği çözmek için .
2) Alternatif Yok:this
Bir üye işlevden bir gösterici veya referans döndürmek için . Bu sık sık yapılır (ve yapılmalıdır) aşırı zaman operator+
, operator-
, operator=
vb:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
Bunu yapmak, bir kod satırında bir nesne üzerinde birkaç işlem gerçekleştirdiğiniz " yöntem zinciri " olarak bilinen bir deyime izin verir . Gibi:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Bazıları bu düşünceyi düşünürken, diğerleri bunu iğrenç bir şey olarak görüyor. Beni ikinci grupta sayın.
3) Alternatif Yok: Bağımlı türlerdeki isimleri çözmek için. Bu, aşağıdaki örnekte olduğu gibi şablonlar kullanılırken ortaya çıkar:
#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) Mevcut Alternatifler: Kodlama stilinin bir parçası olarak, yerel değişkenlerin aksine hangi değişkenlerin üye değişkenler olduğunu belgelemek için. Üye değişkenlerin asla yerellerle aynı ada sahip olamayacağı farklı bir adlandırma şemasını tercih ederim. Şu anda mName
üyeler ve name
yerel halk için kullanıyorum .
Diğer bir durum, operatörleri çağırmaktır. Örneğin
bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
söyleyebilirsin
bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
Hangisi daha okunaklı olabilir. Başka bir örnek de kopyala ve değiştir:
Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
Neden yazılmadığını bilmiyorum swap(temp)
ama bu yaygın görünüyor.
const
(geçici üzerinde üye işlev Type(rhs).swap(*this);
yasal ve doğrudur) ama geçici kutu (derleyici atılmasına neden olmayan bir const referans parametresine bağlamak değil swap(Type(rhs));
de sıra this->swap(Type(rhs));
)
Bunu, yalnızca iki olası ad alanında aynı ada sahip bir sembolünüz varsa kullanmanız gerekir. Örneğin alın:
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
}
Koddaki ilginç noktalarda, myVar'a atıfta bulunmak yerel (parametre veya değişken) myVar'ı ifade edecektir. MyVar olarak da adlandırılan sınıf üyesine erişmek için açıkça "this->" kullanmanız gerekir.
this->
kaçınılması gereken önemsiz bir kullanımdır (sadece yerel değişkene farklı bir ad verin). this
Bu yanıtın tüm gerçekten ilginç kullanımlarından bahsedilmiyor bile.
Bunun diğer kullanımları (özeti okuduğumda ve sorunun yarısını okuduğumda düşündüğüm gibi ...), diğer cevaplarda isim belirsizliğini göz ardı ederek (kötü), mevcut nesneyi dönüştürmek istiyorsanız, onu bir işlev nesnesine bağlamaktır. veya bir üyeye işaretçi ile kullanın.
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)();
}
}
Umarım bunun sadece bu-> üyeden başka kullanımlarını göstermeye yardımcı olur.
this
Parametreler / yerel değişkenler ve üye değişkenler arasındaki belirsizliği gidermek için kullanmanız gerekir .
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
this
İşaretçinin ana (veya diyebilirim, tek) amacı, bir üye işlevi çağırmak için kullanılan nesneyi göstermesidir.
Bu amaçla, sadece this
işaretçi kullanarak sorunu çözebilecek bazı durumlara sahip olabiliriz.
Örneğin, argümanıyla aynı sınıf nesnesiyle üye işlevinde çağırılan nesneyi döndürmemiz gerekir:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
Etkili C ++ kitabında "bu" işaretçinin açık kullanımıyla ilgili başka ilginç bir durum buldum.
Örneğin, şöyle bir const işleviniz olduğunu varsayalım:
unsigned String::length() const
Her çağrı için String'in uzunluğunu hesaplamak istemezsiniz, bu nedenle,
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
Ancak bu derlenmez - nesneyi bir const işlevinde değiştiriyorsunuz.
Hüner bu döküm gerektirir çözmek için bu bir karşı const olmayan bu :
String* const nonConstThis = (String* const) this;
Sonra, yukarıdakileri yapabileceksiniz
nonConstThis->lengthInitialized = 1;
length
değişebilir hale getirebilir , hatta iç içe bir yapıya koyabilirsiniz. Sabitliği ortadan kaldırmak neredeyse hiçbir zaman iyi bir fikir değildir.
const
üye işlevlerinden değiştirilecekse, değiştirilmelidir mutable
. Aksi takdirde, diğer bakıcılar için hayatı daha karmaşık hale getiriyorsunuz.