2012-01-03 12 views
-1

私はコードを持っています。なぜこのコードはコンパイルされますか?

class A 
{ 
public: 
    int foo(int i) 
    { 
     return i; 
    } 
}; 

int foo(int i) 
{ 
    return i; 
} 

int (A::*ptrFoo)(int) = NULL; 
int (*_foo)(int) = NULL; 

int main() 
{ 
    ptrFoo = &A::foo; 
    _foo = foo; 

    (*_foo)++++++++++++++(10); //This dont compile... 

    A a; 
    (a.*ptrFoo)+++++++++++++++++(10); //This compiles ???? 

} 

教えてください。未定義の振る舞い、または何?私はVS2008でそれをコンパイルしました。間違いなくコードの最後の行が正常にコンパイルされます。

+2

'++++++++++++++++ 'はポストインクリメント演算子が7つあります。おそらく、コンパイラは半分に追いついています。 –

+0

あなたはCとC++の両方としてコンパイルしましたか?または、なぜ両方のタグを組み込んだのですか? –

+0

私はそれをC++(VS2008)でコンパイルしました.iは "C"タグを削除します – YAHOOOOO

答えて

2

どちらの式もコンパイルする必要はありません。C++では、関数、メンバー関数、関数型またはメンバ関数へのポインタに対して算術演算を実行できません。プログラム内の2つの式は、それぞれ関数とメンバー関数の算術演算を実行しようとします。

コンパイラが2番目の式を受け入れる場合は、コンパイラのバグが原因です。

1

機能へポインタメンバ関数ポインタと異なることを最初の音符。

最初の例は、通常の関数へのポインタです。それは関数の実メモリアドレスを含んでいます。逆参照すると((*_foo))関数自体が得られ、関数(関数ポインタ)に++などの算術演算は無意味です。

もう一つの話は、クラスのメンバ関数へのポインタは、メモリ内の関数のアドレスを持ちません。実際にコンパイラがメンバ関数をどのように管理するかは、実装固有です。メンバ関数へのポインタには、いくつかのアドレスやコンパイラ固有の情報が含まれている場合があります。このタイプの算術演算も無意味です。

したがって、(a.*ptrFoo)の値はわかりませんが、バグや設計のためにMSVC2008がそれをコンパイルすることができました。

ところで、GCCは2つのステートメントのいずれもコンパイルせず、両方でステートメントを実行しません。

上記は、+または奇数の偶数を入力した場合でもtrueです。とにかく算術演算をしています。 (+の奇数がある場合、関数呼び出しはありません.2番目の例のように、関数を8回インクリメントしてから、最後に残っているのは+です。これは問題ありません。関数/メンバ関数ポインタを変更しようとしています)。

+0

"コンパイラがメンバ関数を管理する方法は実装固有です"非メンバ関数の実装も実装の詳細です。 –

+0

@JamesMcNellis:あなたはそうですが、すべての通常の関数は明示的なアドレスをメモリに持っていますか?しかし、メンバー関数の「アドレス」は、私たちが知っているものではありません。各コンパイラには、クラスの実装に関する独自のパラダイムがあります。 – Hossein

関連する問題