C ++ and Swift: how are C ++ stack frames structured? Are the complications of struct inheritance why Swift doesn't support struct inheritance?
A recent developer briefly discussed the topic of struct
inheritance in Swift (or more precisely, the lack of inheritance struct
in Swift). I assumed that the reason Swift doesn't support inheritance struct
is this:
-
struct
- value types - value types are copied between stack frames Inheritance
- means that the size of a
struct
can change (for example, ifLorry
inherits fromVehicle
andLorry
adds.weightCapacity
, thenLorry
it will take more space thanVehicle
) - Having value type parameters with a size that is not known at compile time will complicate the construction of the stack frame for the caller and data access for the callee
My guess is that it is because of these complications, which would presumably add extra operations to every function call that includes struct
and thus degrades performance, that Swift does not allow inheritance struct
. Is this reasoning correct?
But then I'm at least talking about C ++. C ++ allows inheritance struct
, while C ++ does it with a high degree of performance. This makes me think that my reasoning about Swift not allowing inheritance struct
is wrong. How did C ++ achieve inheritance struct
without negatively impacting performance?
source to share
How does C ++ inherit structure inheritance without negatively impacting performance?
In C ++, the compiler always knows the size struct
. But when the base class is copied by value, the object is "sliced": only the members of the base class are copied, and the new object is in no way associated with the original class.
So, if a function wants to do something with Vehicle
without stripping away its unnecessary identification, it must use a pointer or reference to Vehicle
as the function parameter type or return type. But at this point, you no longer have "copied value types between stack frames".
source to share
Since structs are value types, you must copy them to and from the function. Thus, you could call a non-mutating method with a derived struct, but you could not return the resulting value from it, so
struct Vehicle {
var color: Color
mutating func paintWhite() {
self.color = .White
}
}
struct Lorry: Vehicle ...
var lorry = Lorry(color:.Blue)
lorry.paintWhite() // <- wouldn't work, as paintWhite takes inout Vehicle
Without the ability to invoke mutation methods, structures would be much less useful and much more confusing.
source to share