#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;
}
我有這樣的代碼。它可以在Ubuntu 12.10和13.04下的Windows 8,g ++ 4.7和Clang ++ 3.2(包括x86和x64)下按預期運行MSVC 2012 x64。但是,帶有問號的行在使用MinGW 4.7 x86 或MinGW 4.8 x64(對不起,我以爲我做過)編譯時演示了未定義的行爲。這是鑽石繼承UB在MinGW中的錯誤?
調試器輸出表示在此時鏈接到TargetClass的vtable時出現問題。放置斷點表明TargetClass :: operator string()被加載了嚴重的解除引用的對象。但是,將顯式dynamic_cast置於正確的輸出。
我不知道什麼可能會導致這個問題。如果它是MinGW的一個bug,它一出現就可能被解決,因爲它破壞了C++的一個核心概念。
「未定義的行爲」是語言定義中的一個術語。它意味着只有**,即語言定義不會說明會發生什麼。如果您在運行代碼時看到奇怪的事情發生,它不一定會「演示未定義的行爲」。 –
形式上,代碼需要'#include'頂部的某處。這可能與問題無關。 –