This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:iot-open:introductiontoembeddedprogramming2:cppfundamentals:structuresandclasses [2023/07/11 13:50] – pczekalski | en:iot-open:introductiontoembeddedprogramming2:cppfundamentals:structuresandclasses [2023/11/23 10:21] (current) – pczekalski | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ==== Structures and Classes ==== | + | ====== Structures and Classes ====== |
| - | Structures and classes present complex data types, definable by the developer. Not all C/C++ programming environments provide support for classes (i.e., STM32 in HAL framework mode does not), but luckily, the Arduino framework supports it. Structures, conversely, are part of the C language definition and are present in almost every implementation of software frameworks for IoT microcontrollers. | + | {{: |
| + | Structures and classes present complex data types, definable by the developer. Not all C/C++ programming environments provide support for classes (e.g., STM32 in HAL framework mode does not), but luckily, the Arduino framework supports it. Structures, conversely, are part of the C language definition and are present in almost every implementation of software frameworks for IoT microcontrollers. | ||
| - | === Structures === | + | ==== Structures |
| In C and C++, a structure is a user-defined data type that allows you to combine different types of variables under a single name. | In C and C++, a structure is a user-defined data type that allows you to combine different types of variables under a single name. | ||
| - | A structure primarily groups related variables, forming a complex data type. A custom data structure (type) that can hold multiple variables, each with its own data type. These variables, called members or fields, can be of any built-in or user-defined type, including other structures. | + | A structure primarily groups related variables, forming a complex data type. A custom data structure (type) that can hold multiple variables, each with its data type. These variables, called members or fields, can be of any built-in or user-defined type, including other structures. |
| The sample named structure (equivalent to the complex type), variable declaration and use of member fields are presented below: | The sample named structure (equivalent to the complex type), variable declaration and use of member fields are presented below: | ||
| <code c> | <code c> | ||
| Line 30: | Line 31: | ||
| </ | </ | ||
| - | Structures with type definitions are common when authoring libraries to let library users be able to declare new variables on their own, simply using a type. | + | Structures with type definitions are common when authoring libraries to let library users be able to declare new variables on their own, simply using a type.\\ |
| - | == Manipulating Structure' | + | ** Manipulating Structure' |
| Access to the fields of the structure' | Access to the fields of the structure' | ||
| <code c> | <code c> | ||
| adr1.city = " | adr1.city = " | ||
| adr2.city = " | adr2.city = " | ||
| - | adr3.street = "Rodney"; | + | adr3.street = "Lime Street"; |
| </ | </ | ||
| The structure' | The structure' | ||
| <code c> | <code c> | ||
| - | adr3 = {"Liverpool", "L1 9EX", "27 Rodney", -2.973083901947872, | + | adr3 = {"Gliwice", "44-100", "1 Lime", -2.973083901947872, |
| </ | </ | ||
| In C++, structures can also have member functions that manipulate the data (in C, they cannot). That is not so far from the Classes idea described in the following chapter. | In C++, structures can also have member functions that manipulate the data (in C, they cannot). That is not so far from the Classes idea described in the following chapter. | ||
| - | In the case of using C (or poor implementation of C++ that does not support classes nor member functions, | + | In the case of using C (or poor implementation of C++ that does not support classes nor member functions, e.g. STM32), it is common to prepare a set of data handling functions that operate on the structure referenced with a pointer. A common rule of thumb is the structure is the first argument in the function: |
| <code c> | <code c> | ||
| struct calcdata | struct calcdata | ||
| Line 73: | Line 74: | ||
| int z = fCalcDataAdd(& | int z = fCalcDataAdd(& | ||
| </ | </ | ||
| - | === Classes === | + | |
| - | An extension of the structure' | + | ==== Classes |
| + | Classes were introduced in C++ to extend structures encapsulating | ||
| + | < | ||
| + | <note important> | ||
| Sample class definition is presented below: | Sample class definition is presented below: | ||
| <code c> | <code c> | ||
| class Calculator | class Calculator | ||
| { | { | ||
| - | | + | |
| - | int x,y; | + | int x,y; |
| - | | + | |
| - | x=0; y=0; | + | |
| - | } | + | |
| - | public: | + | |
| - | Calculator() { //Default constructor | + | |
| clear(); | clear(); | ||
| } | } | ||
| - | Calculator(int px, int py) { //Constructor | + | Calculator(int px, int py) { //Another constructor |
| x=px; | x=px; | ||
| y=py; | y=py; | ||
| } | } | ||
| + | ~Calculator(){} //This is dummy destructor | ||
| int Add(){ return x+y; } | int Add(){ return x+y; } | ||
| int Mul(){ return x*y; } | int Mul(){ return x*y; } | ||
| void setX(int px){ x=px; } | void setX(int px){ x=px; } | ||
| void setY(int py){ y=py; } | void setY(int py){ y=py; } | ||
| - | ~Calculator(){} //This is dummy destructor | + | private: //that part is private, and you cannot access it |
| + | void clear(){ | ||
| + | x=0; y=0; | ||
| + | | ||
| }; | }; | ||
| </ | </ | ||
| The code above declares a new type, '' | The code above declares a new type, '' | ||
| + | |||
| **Constructors**\\ | **Constructors**\\ | ||
| There are " | There are " | ||
| Line 107: | Line 112: | ||
| The above code instantiates an object '' | The above code instantiates an object '' | ||
| There can be multiple constructors, | There can be multiple constructors, | ||
| + | |||
| **Destructor**\\ | **Destructor**\\ | ||
| - | A destructor is called automatically when an object' | + | A destructor is called automatically when an object' |
| <code c> | <code c> | ||
| ~Calculator(){} //This is dummy destructor | ~Calculator(){} //This is dummy destructor | ||
| </ | </ | ||
| <note tip>In the embedded world, explicitly implemented destructors releasing allocated memory are rare as for the safety of the software, dynamic allocation of the memory is rather to be avoided; thus, destructors are eventually related to the network connections more than memory management.</ | <note tip>In the embedded world, explicitly implemented destructors releasing allocated memory are rare as for the safety of the software, dynamic allocation of the memory is rather to be avoided; thus, destructors are eventually related to the network connections more than memory management.</ | ||
| + | |||
| **Members**\\ | **Members**\\ | ||
| - | Member fields can be of any type. When marked as '' | + | Member fields can be of any type. When marked as '' |
| **Methods**\\ | **Methods**\\ | ||
| - | A method can have any name other than reserved | + | A method can have any name other than reserved (e.g. for constructors and destructor). Methods marked as '' |
| + | <code c> | ||
| + | // | ||
| + | int z = calc1.Add(); | ||
| + | calc1.setX(10); | ||
| + | calc1.setY(20); | ||
| + | z = calc1.Mul(); | ||
| + | </ | ||
| + | **Class inheritance**\\ | ||
| + | Classes can be inherited. This mechanism enables the real power of C++, where existing models (classes) can be extended with new logic without a need to rewrite and fork existing source code. In the example above, the '' | ||
| + | A code below defines a new type '' | ||
| + | <code c> | ||
| + | class BetterCalculator: | ||
| + | { | ||
| + | public: | ||
| + | BetterCalculator() { | ||
| + | } | ||
| + | BetterCalculator(int px, int py): | ||
| + | } | ||
| + | int Sub(){return x-y;} | ||
| + | }; | ||
| + | </ | ||
| + | Members '' | ||
| + | Instantiation and use are similar to the presented ones in the previous examples: | ||
| + | <code c> | ||
| + | BetterCalculator calc2=BetterCalculator(10, | ||
| + | // | ||
| + | ... | ||
| + | z = calc2.Sub(); | ||
| + | z = calc2.Add(); | ||
| + | // | ||
| + | </ | ||
| + | The description above does not deplete all features of C++ Object Oriented Programming. Please note, however, that in the case of the embedded C++, their implementation can be limited and may not contain all the features of the modern, standard C++ patterns. | ||
| + | **A special note on the libraries with separate definitions (header) and implementation (body)**\\ | ||
| + | Many libraries come with a class definition in the header file (.h) and its implementation in the code file (.cpp). This is convenient for separating use patterns and implementations. A special operator, "::" | ||
| + | The sample header file '' | ||
| + | <code c> | ||
| + | #ifndef h_MYCLASS | ||
| + | #define h_MYCLASS | ||
| + | class Calculator{ | ||
| + | public: | ||
| + | int x,y; | ||
| + | Calculator(); | ||
| + | Calculator(int px, int py); //Another constructor | ||
| + | ~Calculator(); | ||
| + | int Add(); | ||
| + | int Mul(); | ||
| + | void setX(int px); | ||
| + | void setY(int py); | ||
| + | private: | ||
| + | //and you cannot access it | ||
| + | void clear(); | ||
| + | }; | ||
| + | #endif | ||
| + | </ | ||
| + | The implementation code refers to the class definition in the header: | ||
| + | <code c> | ||
| + | #include " | ||
| + | |||
| + | Calculator:: | ||
| + | Calculator:: | ||
| + | Calculator:: | ||
| + | int Calculator:: | ||
| + | int Calculator:: | ||
| + | void Calculator:: | ||
| + | void Calculator:: | ||
| + | void Calculator:: | ||
| + | </ | ||