4
#include <iostream>
#include <sstream>

class VeryBase {
protected:
    int a_;
public:
    VeryBase() : a_(1) {}
    virtual operator std::string() {
        return "0";
    }
};

class Base1 : public virtual VeryBase {
protected:
    int b_;
public:
    Base1() : b_(2) {}
    operator std::string() {
        return "1";
    }
};

class Base2 : public virtual VeryBase {
protected:
    int c_;
public:
    Base2() : c_(3) {}
    operator std::string() {
        return "2";
    }
};

class TargetClass : public Base1, public Base2 {
protected:
    int d_;
public:
    TargetClass() : d_(4) {}
    operator std::string() {
        std::ostringstream s;
        s << a_ << ' ' << b_ << ' ' <<  c_ << ' ' << d_ << std::endl;
        return s.str();
    }
};

int main()
{
    VeryBase* a = new TargetClass;
    Base1* b = dynamic_cast<Base1*>(a);
    Base2* c = dynamic_cast<Base2*>(a);

    std::cout << std::string(*a) //1 2 3 4
              << std::string(*b) //1 2 3 4
              << std::string(*c) //? ? ? ?
              << std::endl;
}

私はこのようなコードを持っています。Windows 8 の MSVC 2012 x64、Ubuntu 12.10 および 13.04 の g++ 4.7 および Clang++ 3.2 (x86 と x64 の両方) で期待どおりに動作します。ただし、疑問符のある行は、MinGW 4.7 x86 でコンパイルすると未定義の動作を示します。または MinGW 4.8 x64(申し訳ありませんが、私はそう思っていました)。

デバッガーの出力は、その時点で TargetClass の vtable へのリンクに問題があることを示しています。ブレークポイントを配置すると、TargetClass::operator string() が不適切に逆参照されたオブジェクトでロードされていることがわかります。ただし、明示的な dynamic_cast を配置すると、正しい出力が得られます。

何がこの問題を引き起こす可能性があるのだろうか。MinGW のバグであれば、C++ のコア コンセプトの 1 つを壊すため、おそらくすぐに解決されるでしょう。

4

3 に答える 3

1

これは、コンパイラのバグ (または のランタイム サポートのバグdynamic_cast) のようです。注意深く調べていませんが、コードは正しいように見えます。もちろん、投稿されたコードが問題を引き起こすコードではない場合を除きます。

于 2013-05-31T23:03:04.460 に答える
1

私はちょうどテストしました:

  • 32 ビットおよび 64 ビット MinGW-w64 GCC 4.6/4.7/4.8 ビルド
  • MSVC 11.0 および MSVC 11.0 11 月 CTP
  • GCC 4.6 libstdc++ を使用する 32 ビット Clang 3.2

すべてWindows上で、すべて出力を提供します:

1 2 3 4
1 2 3 4
1 2 3 4

これは、Linux の Clang および GCC と同じです。

これが未定義の動作であるかどうかはわかりません。使用したことはありませんdynamic_cast

于 2013-06-02T10:06:37.833 に答える