Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwriting an instance of a subclass with an instance of a superclass

Tags:

c++

types

casting

Trying to figure something out (in Ada, actually) I came up with the following code. Why is it legal?

class Superclass {
public:
    virtual void Announce() {
        printf("I am the superclass\n");
    }
};

class Subclass : public Superclass {
public:
    void Announce() {
        printf("I am the subclass\n");
    }
};

int main() {
    Superclass osuper;
    Subclass osub;

    Superclass* p = &osub;
    *p = osuper;
    osub.Announce();

    return 0;
}

In main(), I create an instance of Subclass, then physically overwrite it with an instance of Superclass. I then successfully call a method of Subclass on the overwritten (and so corrupted) object.

I can't directly assign osub = osuper, because that makes no sense, but by going via a pointer I seem to bypass that. The above code compiles fine with no warnings, but by the time I call osub.Announce() the memory inside osub no longer contains a valid Subclass object.

This can't possibly be type safe (or even, like, ordinarily safe), but the compiler seems perfectly happy. Why?

like image 298
David Given Avatar asked Jan 11 '23 00:01

David Given


2 Answers

Using the = operator on an object is not invalid, and it doesn't overwrite anything, a default copy constructor will be used. If you want to really overwrite the object in memory, try memcpy(p, &osub, sizeof(Superclass)). Now THAT would be an overwrite :)

See http://www.cplusplus.com/articles/y8hv0pDG/

like image 146
glezmen Avatar answered Jan 23 '23 06:01

glezmen


You are invoking the copy-assignment operator, not "physically overwriting". This is a function which, like any other function besides a constructor, may modify members of the object which already exist, it's not "magic".

Your object has no member variables so the implicitly-generated operator= call is a no-op. There is no "corrupt object". osub.Announce(); calls Subclass::Announce because osub is a Subclass.

The actual function called is Superclass::operator=(Superclass const &);.

The function Subclass::operator=(Subclass const &); loses in overload resolution because osuper does not implicitly convert to Subclass const &.

What you might be getting at is that if Subclass had member variables then the line *p = osuper; may leave the osub object in a state that was not intended by the designer of Subclass.

like image 31
M.M Avatar answered Jan 23 '23 06:01

M.M