2011-07-05 6 views
8

は、私はC++に関連する2つの質問があります。多くの教科書にキーワード "this"の実際の意味は何ですか?

を、キーワードthis呼び出すオブジェクトへのポインタです。正しい? 、

sizeof(a) : 4 
sizeof(b) : 8 
Base::g() 
sizeof(*this) : 4 
Base::f() 
Base::g() 
sizeof(*this) : 4 // why 4 bytes not 8 bytes????????? 
Derived::f() 

this場合は、呼び出し元のオブジェクトを指している:

struct Base 
{ 
    void g(); 
    virtual void f(); 
}; 

void Base::f() { 
    cout << "Base::f()" << endl; 
} 

void Base::g() { 
    cout << "Base::g()" << endl; 
    cout << "sizeof(*this) : " << sizeof(*this) << endl; 
    this->f(); 
} 

struct Derived : public Base 
{ 
    int d; 
    void f(); 
}; 

void Derived::f() 
{ 
    cout << "Derived::f()" << endl; 
} 

int main() 
{ 
    Base a; 
    Derived b; 

    cout << "sizeof(a) : " << sizeof(a) << endl; 
    cout << "sizeof(b) : " << sizeof(b) << endl; 

    a.g(); 
    b.g(); 
} 

上記のコードは次の出力を生成します。私は、コードで遊ぶのが好きなように

は、私は、次の簡単なコードを書きました呼び出すオブジェクトがbであるため、sizeof(*this)の2行目が4ではなく8を出力しますか?ここで実際に何が起こっていますか? thisは降格されましたか?

thisの場合はthis->f()が正しい関数を呼び出す方法、Baseを入力することが降格されましたか?私は本当に混乱しています。

+0

てみてください():それはBaseのサイズは4バイトであることを知っているので、コンパイラは、基本的に、このように、その文をリライトしますそれが何を出すかを見てください。 Base :: g()の呼び出しは、それがサブクラスの一部であることを知らない。その場合、*これは正当にBaseを参照し、Derivedは参照しません。 –

+0

そして 'sizeof(* this)'がコンパイル時にどのように評価されると思いますか?これは 'sizeof(Base)'と変わりません。 –

答えて

12
void Base::g() { 
    cout << "Base::g()" << endl; 
    cout << "sizeof(*this) : " << sizeof(*this) << endl; 
    this->f(); 
} 

行われる必要がある重要な違いはsizeofコンパイル時オペレータ、ないランタイムオペレータであるということです。コンパイラは式sizeof(*this)を「thisが指し示すオブジェクトのサイズ」と解釈します。これはBase::gのスコープ内でタイプBaseのオブジェクトになります。派生:: Fにはsizeofの呼び出し(* this)を追加すること

cout << "sizeof(*this) : " << 4 << endl; 
+0

ああ、そうです。私は 'sizeof(* this) 'の代わりに' this'の値を出力するようにコードを修正し、&bと&aと比較しました。答えは私の期待に合っていた。 Umhhh .. Thanksssssssssss。 – Eto700

0

thisは、関数が非静的メンバであるオブジェクトへの定数値のポインタです。つまり、thisを実行可能な値にするには、クラスの非静的メンバーでのみ使用する必要があります。注意:静的でないメンバ関数(instance.functionまたはinstance-> function)を呼び出すには、オブジェクトインスタンスを使用する必要があります。 thisは "インスタンス"へのポインタです。

gは、Baseのメンバーであるため、サイズが決して8ではない理由があります。 gの場合、thisはタイプBase *constであるため、*thisはタイプBase&です。 sizeof(Base)は4です。仮想メンバーであっても、これは変更されません。 gの実装のタイプは常にBase *constになります。事実上オーバーライドされたバージョンは異なる型を持ちますが、それらを実装するクラスの型だけです。

thisの型は多型に従わない。それは正確に関数が定義された型だけを持っています。

+0

'g'が仮想であっても、' g'は派生クラスによって決して上書きされないので問題にはなりません。 –

+1

'g 'が仮想であったとしても、派生型を介して呼び出されたwhterhにかかわらず、' sizeof(* this) 'は' Base :: g() 'では常に4になります(例えば、 'g()'はオーバーライドされませんでした)。私はこれがあなたの最後の文で言うことですが、2番目の段落は、 'sizeof(* this)'が 'g()'の基本実装であっても派生型に「追随する」と読者に考えさせるかもしれません。 –

1

Baseは、派生オブジェクトの一部であるものについては表示/アクセス/認識できません。したがって、sizeofは、オブジェクトの表示可能部分のみを報告します。さらに多くの点では、Baseのメソッドのsizeofはサブクラスがあるかどうかわかりません(Baseは再コンパイルせずにサブクラス化することができます)ので、それ以外のものについては報告できません。 (sizeofは実行時ではなくコンパイル時に計算されます)

0

Base::fは仮想なので、正しい関数fが呼び出されます。これはコンパイラに、Base*->f()への呼び出しが要求されたときに、呼び出されたメンバーの実際のオブジェクトのvtableで呼び出し先の実際のアドレスが検索されることを通知します。

タイプ問題のthisはなぜsizeof(*this) == sizeof(Base)ある、Base*であるが、そのvtableのは、派生オブジェクトに属し、したがってfへの関数呼び出しをオーバーライドに行きます。

関連する問題