Suppose a hierarchy with two unrelated polymorphic classes PCH
and GME
, a subclass PCH_GME : public GME, public PCH
, and an object gme_pch
of type PCH_GME*
.
Why does the following sequence of casts of gme_pch
"break" the cast back to the object's original type GME_PCH*
:
GME_PCH *gme_pch = new GME_PCH();
GME *gme = gme_pch;
PCH *pch = (PCH*)gme;
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
// same_as_gme_pch is NULL
whereas the following code does not break the casts:
GME_PCH *gme_pch = new GME_PCH();
PCH *pch = gme_pch;
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
// address of same_as_gme_pch == gme_pch
Question: Isn't each pointer always pointing to the same object, and shouldn't then the result of the final cast back to the original type always be the same?
Just for making it easier to try things out, see the following code demonstrating variants of the above mentioned cast sequences; some working, some not:
class PCH { // PrecachingHint
public:
virtual std::string getHint() const = 0;
};
class GME { // GenericModelElement
public:
virtual std::string getKey() const = 0;
};
class GME_PCH : public GME, public PCH {
public:
virtual std::string getHint() const { return "some hint"; }
virtual std::string getKey() const { return "some key"; }
};
void castThatWorks() {
GME_PCH *gme_pch = new GME_PCH();
PCH *pch = gme_pch;
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
std::cout << ((same_as_gme_pch == nullptr) ? "cast did not work." : "cast worked")<< std::endl;
}
void castThatWorks2() {
GME_PCH *gme_pch = new GME_PCH();
GME *gme = gme_pch;
PCH *pch = dynamic_cast<PCH*>(gme);
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
std::cout << ((same_as_gme_pch == nullptr) ? "cast did not work." : "cast worked")<< std::endl;
}
void castThatDoesntWork() {
GME_PCH *gme_pch = new GME_PCH();
GME *gme = gme_pch; // note: void* gme = gme_pch breaks the subsequent dynamic cast, too.
PCH *pch = (PCH*)gme;
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
std::cout << ((same_as_gme_pch == nullptr) ? "cast did not work." : "cast worked")<< std::endl;
}
void castThatDoesntWork2() {
GME_PCH *gme_pch = new GME_PCH();
GME *gme = gme_pch;
PCH *pch = reinterpret_cast<PCH*>(gme);
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
std::cout << ((same_as_gme_pch == nullptr) ? "cast did not work." : "cast worked")<< std::endl;
}
void castThatDoesntWork3() {
GME_PCH *gme_pch = new GME_PCH();
GME *gme = gme_pch;
PCH *pch = static_cast<PCH*>(static_cast<void*>(gme));
GME_PCH *same_as_gme_pch = dynamic_cast<GME_PCH*>(pch);
std::cout << ((same_as_gme_pch == nullptr) ? "cast did not work." : "cast worked")<< std::endl;
}
int main() {
castThatWorks();
castThatWorks2();
castThatDoesntWork();
castThatDoesntWork2();
castThatDoesntWork3();
}
Aucun commentaire:
Enregistrer un commentaire