1) A derived type can be assigned to a variable of type base. That's because a base variable can be used to call all public functions and member variables in the base class. Since a derived object has all those same functions and member variables as the base class, calling those functions and member variables for a derived object that is masquerading as a base object will succeed.
2) However, you cannot assign a base type to a derived class type. That's because a variable of type derived can be used to call any public function or member variable in the derived class. But if a base object is hiding in a variable of type derived, calling some functions and member variables in the derived class will not succeed because none of the functionality added by the derived class will be present in a base object.
The bottom line is: transpose() returns a Matrix object, so your variable must be of type Matrix. Why would you expect that a Matrix object returned by transpose() to have the functionality of a Matrix3D object? You can't squeeze lemons and get orange juice.