15

クラス/構造体とそれぞれのオブジェクトがメモリ内でどのように配置されるかを理解するためにC++で実験しており、クラス/構造体の各フィールドがそれぞれのオブジェクトへのオフセットであることを理解しました(したがって、メンバー変数ポインターを持つことができます)。

メンバー関数ポインターを持つことができても、次のコードが機能しない理由がわかりません。

struct mystruct
{
    void function()
    {
        cout << "hello world";
    }
    int c;
};

int main() 
{ 
    unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);
    unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function); // ERROR - error C2276: '&' : illegal operation on bound member function expression



    return 0;
}

私の質問は:なぜその行は

unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);

コンパイルして、構造体と行の先頭からの「c」フィールドのオフセットを返します

unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function);

コンパイルすらしませんか?

4

2 に答える 2

19

メンバー関数またはそれらへのポインターは、オブジェクトに格納されません。(virtual関数は通常、オブジェクトが単一のポインターを持つテーブルに格納されたポインターを介して呼び出されます)これはメモリの膨大な浪費になります。これらは通常、コードメモリセクションに格納され、コンパイラに認識されます。オブジェクト(*this)は通常、非表示のパラメーターとして渡されるため、関数は、呼び出されたときにどのオブジェクトを操作するかを認識します。

だから、素人の言葉で言えば、あなたは

 0x10001000    void A::foo
 ..........    {code for A::foo}

 push a;
 call A::foo (0x10001000)
 pop a;

a呼び出しているオブジェクトはどこにありますかfoo

于 2013-03-22T14:14:01.883 に答える
4

メンバー関数ポインタは実際にはオブジェクトに格納されていません。必要はありません。C ++標準では、仮想関数の実装方法を正確に指定していませんが、仮想メンバー関数の一般的な方法では、各オブジェクトに関数ポインターのテーブルへのポインターが含まれています。このポインターはvtableポインターと呼ばれます。

StanleyLippmanによる「InsidetheC ++ objectmodel」を手に入れようとするかもしれません。

または、当時のホームページサイトが消える前に、かつてウィキペディアのポインタの記事から参照されていた古いポインタチュートリアルを手に入れようとするかもしれません。


2番目の質問に関しては、アドレスを取得p->memberFuncするとコンパイラが少し窒息するのはなぜですか。式には型がありません。これは構文エンティティであり、引数リストを適用して関数を呼び出すことができます。

ウィットに、

struct S
{
    void foo() {}
};

#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
    S* p = 0;
    typeid( &p->foo );
} 

コンパイル:

[W:\ dev \ test]
> g ++ foo.cpp
foo.cpp:関数内'int main()':
foo.cpp:12:17:エラー:ISO C ++は、バインドされたメンバー関数のアドレスを取得して、メンバー関数へのポインターを形成することを禁止しています。'&S ::foo'[-fpermissive]と言います
foo.cpp:12:22:警告:計算された値は使用されません[-Wunused-value]
foo.cpp:12:22:警告:ステートメントは効果がありません[-Wunused-value]

[W:\ dev \ test]
> _
于 2013-03-22T14:12:58.787 に答える