1
#include <iostream>
class A
{
public:
    A()
    {
        std::cout << "\n A_Constructor \t" << this <<std::endl;
    }
    void A_Method()
    {
        std::cout <<"\n A_Method \t" << this <<std::endl;
    }
};
class B:public A
{
public:
    B()
    {
        std::cout <<"\n B_Constructor \n";
    }
    void B_Method()
    {
        std::cout <<"\n B_Method \t" << this <<std::endl;
    }
};

int main()
{
    A *a_obj = new A;
    B *b_obj = static_cast<B*> (a_obj);  // This isn't safe.
    b_obj->B_Method();      
    getchar();
    return 0;
}

出力:

A_Constructor 001C4890
B_Method 001C4890

型変換には実行時チェックが含まれstatic_castないため、安全ではありません。しかし、この例では、私は私が予期していなかったものを手に入れました。への呼び出しがないためB::B()、そのメンバーは誰からも呼び出されないようにする必要がありますb_obj。それにもかかわらず、私は出力を得ました。

この単純なケースでは、安全ではないことがわかっていますが、成功した可能性があります。私の疑問は-

  • の呼び出しはありませんが、どうすればメンバー機能B::B()にアクセスできましたか。class B
  • 誰かが例を挙げてください。これは安全ではなく、間違っている可能性があります(前に示したものは悪い例として役立つかもしれませんが、さらに良いですが)。

Visual Studio 2010で、\Wallオプションを設定して実行しました。

4

3 に答える 3

4

これは未定義の動作です。UB が原因でクラッシュすることがあります。時々それは「うまくいく」ようです。この場合、悪いことがあまり起こらなかったとしても、これを行うべきではないというあなたの意見は正しいです。

于 2011-01-10T17:52:54.850 に答える
0

この特定のケースがUBであるとは思えません。まず、ポインターをある型から別の型にキャストするだけです。仮想継承や多重継承がないため、ポインタの調整は行われず、基本的にポインタの値は変わりません。確かに、それは間違った型のオブジェクトを指していますが、B メンバーがあったとしてもアクセスしない限り、誰が気にするでしょうか? また、ポインターの調整が含まれていたとしても、それが指すメモリにアクセスしなくても問題ありません。

次に、この例では B のメソッドを呼び出します。これは仮想ではないため、隠し引数を使用した通常の関数呼び出しにすぎませんthis( と考えてくださいB::B_Method(this))。さて、this間違った型のオブジェクトを指していますが、もう一度言いますが、誰が気にしますか? それが行う唯一のことは、それを印刷することであり、これは常に安全なことです.

実際、NULL ポインターを使用してメソッドを呼び出すこともできます。メソッドが仮想ではなく、 が指すものにアクセスしようとしない限り、これは機能しますthis。私はかつて多くのプログラムで使用されるライブラリを持っていました。このライブラリには、明示的に構築する必要があるシングルトンのようなクラスがありましたが、実際にそれを行ったプログラムはありませんでした。インスタンス ポインタは、グローバルであるため、デフォルトで NULL に初期化されました。クラスにはデータメンバーがまったくないため、完全に機能しました。次に、いくつか追加したところ、すべてのプログラムが突然クラッシュし始めました。理由が分かった時は大爆笑でした。存在すらしていないオブジェクトを使用しています。

于 2011-01-10T18:45:18.640 に答える
0

あなたがしようとしているのは未定義の動作であるため、何かが起こる可能性があります。データメンバーにアクセスしようとしないため(何も持っていないため)、これはうまくいくようです(そしておそらくうまくいくでしょう)。両方のクラスにいくつかのデータ メンバーを追加し、メソッドからアクセスしてみてください。動作が完全に予測不能に変わることがわかります。

于 2011-01-10T17:57:44.510 に答える