Why can't a Base class object be assigned to a Derived class object?

Inheritance is an "is-a" relationship, but it's one-way only.

If you have e.g.

struct Base { /* ... */ };
struct Derived : Base { /* ... */ };

Then Derived is a Base, but Base is not a Derived.

That's why you can assign or initialize a base-class instance with a derived object (but beware of object slicing), but not the other way around.


A derived object is a base object, with additional information.

You can initialize a complete base object from the base part of a derived object, no problem.

But if you want to construct a derived object from just a base object, what should the additional information be initialized with?

If you want to provide defaults for that additional information, you can do so by declaring a Derived(Base const &) constructor. But since it does not work in the general case, it isn't done for you.


In general a C++ compiler will disallow the assignment of a object of a base class to a derived one as, in a sense, the derived class is a superset of the base class: i.e. it wouldn't know how to to deal with any members that are specific to the derived class.

That said, you can handcode such a possibility by an appropriate overload of the assignment operator and an appropriate constructor in the derived class.

Aside from perhaps overcomplicating the language, I don't see why a trivially copyable base class instance could not be assigned to a derived class that contains no additional members. But this is not implemented in any C++ standard at the time of my writing. Furthermore, to my mind at least, the consequence of having any uninitialised derived class members and bypassed derived class constructors doesn't require materially more consideration on the part of a programmer than the perils of object slicing if a derived class instance is assigned to a base class! In other words, I don't think the hackneyed retort "because it makes no sense" makes much sense in itself.

Reference: http://en.cppreference.com/w/cpp/types/is_trivially_copyable