2

C++ で奇妙なことに遭遇しましたが、その理由がわかりません。

私はこのようなクラスを持っています

ヘッダファイル

class foo
{
public:
    void call_foo();

    int get_foo();

    int get_foo(int val);
};

ここにcppファイルがあります

#include "foo.h"
#include <iostream>

using namespace std;

void foo::call_foo()
{
    int i = 0;
    int j = 33;
    cout << i + j << endl;
    cout << "Hello, Foo" << endl;
}

int foo::get_foo(int val)
{
    int a = 345;
    int rc = val + a;
    cout << rc << endl;
    return rc;
}

int foo::get_foo()
{
    int a = 100;
    int d = 23;
    int rc = a + d;

    cout << rc << endl;
    return rc;
}

以下のようにコードを使用してテストします

int main()
{
    int* val = new int[100];

    foo* foo_ptr;
    foo_ptr = (foo*)val;
    foo_ptr->call_foo();
    foo_ptr->get_foo();
    foo_ptr->get_foo(100);

    delete [] val;
    return 0;
}

それから私はそれをコンパイルして実行します。

clang++ foo.cpp main.cpp

Apple LLVM バージョン 5.0 (clang-500.2.79) os x 10.9

int ポインターをオブジェクト ポインターに変換し、そのメソッドを呼び出すと、機能します。とても奇妙!何が起こっているのか知っている人はいますか?

私の理解でなぜそれが機能するのかについて、ブログに記事を書きました。ありがとうございました!! オブジェクト構造、仮想関数テーブルについて。ただの中国語版:)

4

4 に答える 4

2

あなたが経験していることは、未定義の動作と呼ばれます。

未定義の動作とは、「何でも起こり得る」という意味です。 ここにあるものはすべて、コードが機能した、期待どおりに動作した、または期待どおりに動作しなかった(クラッシュなど) という錯覚を含みます。

未定義の動作を引き起こすコードは、常に欠陥のあるコードです。何が起こるかを予測できないという理由だけで、未定義の動作に頼ることはできません。

この場合、メソッドの呼び出しが機能しているように見える理由は、実際には、クラスのインスタンスが非staticメソッドのそれぞれのコードの独自のコピーを取得しないためです。代わりに、 のすべてのインスタンス間で共有されるコードのコピーが 1 つありますfoo。そのコードへのポインターは決して変更されないため、(誤って) ポインターへのポインターを解決し、fooそのポインターを介してメソッドの 1 つを呼び出すと、呼び出すと予想された実際のメソッドが実際に呼び出されました。ただし、これはすべて未定義の動作であり、コードを修正する必要があります。

于 2013-10-30T16:39:47.393 に答える
0

クラスにはメンバーも仮想関数もないため、任意のポインターを介してメンバー関数を呼び出すと、静的にバインドされた関数呼び出しがあり、無効なメモリアクセスを行わないため、「機能」します。仮想関数を呼び出したり、メンバー変数にアクセスしようとすると、悪いことが起こります。

于 2013-10-30T16:41:44.270 に答える