This is day 02 of the Two weeks of C++ series. I normally post every two days, but I’ve been more focused on my mobile app recently (React Native). Now I’m back to keeping it 50/50 :) Let’s keep going.
Today I’m learning about user-defined types, which are types built out of the built-in types using C++’s abstraction mechanisms.
The standard library of C++ mainly consists of user-defined types.
I also point out stuffs not related to the current subject. I admit, it’s not smart, but since those are personal notes, I know where to find them ;).
new operator allocates memory from an area called free store. Always destroy, using
delete, memory allocated with
new to avoid memory leaks. Just like
free in C.
The free store == dynamic memory == heap.
Depending on a function declaration and how you pass a structure to it, here’s how to access the structure’s elements:
Remember I said I would talk about using an argument through reference in the last post? Note that we’re not dereferencing
rv to be able to access its
sz element or any other possible elements whatsoever.
However, we would need to dereference pv, because it’s a pointer. In this example, it’s a struct, hence the
That’s how C++ works, keep this in mind.
Classes allow to distinguish between the interface to a type and its representation/implementation. The interface is defined by the public members and the representation - the private members - is only accessible through this interface.
NOTE: It’s always good to initialize the elements of your class in the same order you declared them because the compiler will always initialize the elements based on the order they were declared in the class, whether you like it or not.
The reason is, normally, when you destroy allocated memories, you use a reverse order method so that you really don’t miss any of them, in case a variable on top depends on one below.
Well every class can have a destructor that uses the same method. So to ensure that properties were always destroyed in the correct reverse order, the simplest solution was to choose the order of declaration over the order of initialization.
It’s not an error when you don’t do it that way, it’s just a warning when you use the -Wall flag in your compilation command.
Here’s how we would initialize and use our
Notice how we can access the vector’s elements through an array-like notation? That’s the power of
subscripting operator overloading.
Nothing new about unions really, except for this great advice:
It’s good to encapsulate a union and its type field in a structure/class to ensure they correspond to each other instead of plainly using them in the open. Here’s an example of a good way to do it:
This is a well known advice among 42 students. For some reason I decided to put it here anyway. Maybe this chapter was too short :P
On top of the basic
enum that we already know, C++ provides
scoped enums. I gotta say, I love it!
It’s really just an enum improved with some class features like operators. Here’s a basic example:
As you can see, unlike basic enums, the type of a scoped enum is not interchangeable with an int type. This prevents accidental misuses of constants. Also, you must use the namespace of the enum to be able to use it.
Here’s one way to create an operator for scoped enums:
Isn’t this beautiful? Could be even better with templates but that’s for later. Here’s what a basic usage of this would be:
Notice how we had to explicitly cast it before printing it out? Unlike a basic enum, a scoped enum is not implicitly convertible to its integer value.
You’ll notice I don’t go too deep into some new terms, like
subscripting operator overloading in classes. That’s because they are coming in day 04, so for now, look them up to be ready for them later.
Here’s what to remember for the day
- Organize related data into structures (structs or classes)
- Represent the distinction between an interface and an implementation using a class
- A struct is simply a class with its members public by default
- Define constructors to guarantee and simplify initialization of classes
nakedunions; wrap them in a class/struct together with a type field
- Prefer class enums over basic enums to minimize surprises
- Define operations on enums for safe and simple use