When should I define a type as a struct or as a class?
I know that struct are value types while classes are reference types. So I wonder, for example, should I defin
Read "D"iving Into the D Programming Language
In D you get structs and then you get classes. They share many amenities but have different charters: structs are value types, whereas classes are meant for dynamic polymorphism and are accessed solely by reference. That way confusions, slicing-related bugs, and comments à la // No! Do NOT inherit! do not exist. When you design a type, you decide upfront whether it'll be a monomorphic value or a polymorphic reference. C++ famously allows defining ambiguous-gender types, but their use is rare, error-prone, and objectionable enough to warrant simply avoiding them by design.
For your Stack
type, you are probably best off defining an interface
first and then implementations thereof (using class
) so that you don't tie-in a particular implementation of your Stack
type to its interface.
Reason #1 to choose struct vs class: classes have inheritance, structs do not. If you need polymorphism, you must use classes.
Reason #2: structs are normally value types (though you can make them reference types if you work at it). Classes are always reference types. So, if you want a value type, choose a struct. If you want a reference type, it's easiest to go with a class.
Reason #3: If you have a type with a lot of data members, then you're probably going to want a reference type (to avoid expensive copying), in which case, you're probably going to choose a class.
Reason #4: If you want deterministic destruction of your type, then it's going to need to be a struct on the stack. Nothing on the GC heap has deterministic destruction, and the destructiors/finalizers of stuff on the GC heap may never be run. If they're collected by the GC, then their finalizers will be run, but otherwise, they won't. So, if you want your type to automatically be destroyed when it leaves scope, you need to use a struct and put it on the stack.
As for your particular case, containers should normally be reference types (copying all of their elements every time that you pass one around would be insanely expensive), and a Stack
is a container, so you're going to want to use a class unless you want to go to the trouble of making it a ref-counted struct, which is decidedly more work. It just has the advantage of guaranteeing that its destructor will run when it's not used anymore.
On a side note, if you create a container which is a class, you're probably going to want to make it final so that its various functions can be inlined (and won't be virtual if that class doesn't derive from anything other than Object
and they're not functions that Object
has), which can be important for something like a container where performance can definitely matter.