2009-04-01 13 views

答えて

1

インテル®C++コンパイラーの場合、Linuxの場合、オブジェクトの始まりであることがわかりました。

コード:

#include <cstdio> 

class A 
{ 
    int a, b; 
public: 
    A(int a1, int b1): a(a1), b(b1) {} 
    virtual void p(void) { printf("A\n"); } 
}; 

class B: public A 
{ 
public: 
    B(int a1, int b1): A(a1, b1) {} 
    void p(void){ printf("B\n"); } 
}; 

int main(void) 
{ 
    A a(1, 2); int p=10; A a1(5, 6); 
    B b(3, 4); int q=11; B b2(7, 8); 

    a.p(); 
    b.p(); 

    int * x=(int*)&a; 
    printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]); 
    x=(int*)&b; 
    printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]); 
} 
0

「機能の始めに」とはどういう意味ですか?とにかく、Windowsコンパイラはvptrをオブジェクトのオフセット0に置き、Unixコンパイラは最後のメンバデータの後ろに置く。 IntelはWindowsとUnixの両方のコンパイラを作成しています.Witバージョンではvptrを最初に、* nixバージョンはオブジェクトの最後に置きます。

0

オブジェクト内のvtableポインタの位置は、オペレーティングシステムに関係しません。これはコンパイラや他のツールの慣例にすぎません。

Sid Datta、あなたはICCからその情報をコンパイルされたモジュールを逆アセンブルすることで発見できます。

3

あなたはいつもこれと派生クラスの最初のアドレスが配置されている場所を見ることができます:私のLinuxボックスの

#include <stdio.h> 

class foo 
{ 
public: 
    virtual int do_foo()=0; 
}; 

class bar : public foo 
{ 
public: 
    int bar; 
    int do_foo() {printf ("%08x %08x\n", this, &bar);} 
}; 

int main() 
{ 
    bar a_bar; 
    a_bar.do_foo(); 
} 

、結果は次のとおりです。

bfdbef3c bfdbef40 

...ですまさにあなたが期待するものです:最初のポインタプラス仮想関数ポインタのサイズは、2番目のポインタの位置です。

+0

なぜプログラムがコンパイルするバグではないのですか? (仮想do_foo関数は 'bar'クラスで定義されていません)barクラスは実際に 'do_foo'メンバーを持っていますが、仮想クラスではありません。 – Arafangion

0

除き、C++標準では、このような内容を定義していないとして、あなたの質問に本当の答えは、非常に有用であることを行っていない、あなたの好奇心を満たすために。したがって、どのコンパイラベンダーも、これらの機能を適切に実装できます。 これは、C++用のクロスプラットフォームABI(アプリケーションバイナリインタフェース)が存在しない理由の1つです。

+0

私はIntel C++(icpc)コンパイラを指定した理由を理解しています。 しかし、私は答えを見つけたので、そのすべての良い!とにかく、ありがとう :) –

関連する問題