Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:iot-open:introductiontoembeddedprogramming2:cppfundamentals:structuresandclasses [2023/07/11 14:37] pczekalskien: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.+{{:en:iot-open:czapka_b.png?50| General audience classification icon }}{{:en:iot-open:czapka_e.png?50| General audience classification icon }}\\ 
 +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:
 </code> </code>
  
-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's Data ==+** Manipulating Structure's Data **\\
 Access to the fields of the structure's member variables (short: members, fields) is possible using the "." (dot) operator. Access to the fields of the structure's member variables (short: members, fields) is possible using the "." (dot) operator.
 <code c> <code c>
 adr1.city = "Gliwice"; adr1.city = "Gliwice";
 adr2.city = "Oslo"; adr2.city = "Oslo";
-adr3.street = "Rodney";+adr3.street = "Lime Street";
 </code> </code>
 The structure's data can be initialised member by a member or at once using the simplified syntax. Order is meaningful, and types need to fit the definition (C++ only): The structure's data can be initialised member by a member or at once using the simplified syntax. Order is meaningful, and types need to fit the definition (C++ only):
 <code c> <code c>
-adr3 = {"Liverpool", "L1 9EX", "27 Rodney", -2.973083901947872, 53.401615049766406 };+adr3 = {"Gliwice", "44-100", "1 Lime", -2.973083901947872, 53.401615049766406 };
 </code> </code>
 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, i.e. 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:+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(&args); //z equals to 24 now int z = fCalcDataAdd(&args); //z equals to 24 now
 </code> </code>
-=== Classes === + 
-Classes were introduced in C++ to extend structures that encapsulate data and methods (functions) to process this data. A method presented above in the structure context brings an overhead with a need to pass a pointer to the structure for each call. Moreover, it makes access levels tricky, i.e. when you do not want to expose some functions but rather use them for internal data processing. Thus classes can be considered as an extension of the structures.+==== Classes ==== 
 +Classes were introduced in C++ to extend structures encapsulating data and methods (functions) to process this data. A method presented above in the structure context brings an overhead with a need to pass a pointer to the structure for each call. Moreover, it makes access levels tricky, e.g. when you do not want to expose some functions but use them for internal data processing. Thusclasses can be considered as an extension of the structures.\\ 
 +<note>Classes are an important part of IoT programming as they bring an idea of the digital twin to low-level programming: a class used to represent a single piece of hardware, e.g. a sensor and provide its current state, access to the data it grabs and gives access to the operations on the hardware. Thus, in most IoT projects, each device external to the MCU that composes an IoT device is represented by one or more classes on the software side.</note>
 <note important>Classes are legit only for C++ and not in regular C implementations.</note> <note important>Classes are legit only for C++ and not in regular C implementations.</note>
 Sample class definition is presented below: Sample class definition is presented below:
Line 101: Line 104:
 </code> </code>
 The code above declares a new type, ''Calculator'', with member fields (members in short) ''x'' and ''y'' and methods (functions) ''Calculator, Add, Mul, setX'' and ''setY''. Some are marked as ''private:'' and accessible only from the code of the functions (methods) within the class; some are exposed to external users when marked as ''public:''.\\ The code above declares a new type, ''Calculator'', with member fields (members in short) ''x'' and ''y'' and methods (functions) ''Calculator, Add, Mul, setX'' and ''setY''. Some are marked as ''private:'' and accessible only from the code of the functions (methods) within the class; some are exposed to external users when marked as ''public:''.\\
 +
 **Constructors**\\ **Constructors**\\
 There are "special" functions whose name is equivalent to the class name in this example above. Those are called constructors and are executed once the object of the class type is instantiated: There are "special" functions whose name is equivalent to the class name in this example above. Those are called constructors and are executed once the object of the class type is instantiated:
Line 108: Line 112:
 The above code instantiates an object ''calc1'' of the class ''Calculator'' and calls the constructor explicitly ''Calculator(int px, int py)''. The other constructor, ''Calculator()'', is the default one, and if not explicitly called by the code developer, it is automatically called when the object is instantiated.\\ The above code instantiates an object ''calc1'' of the class ''Calculator'' and calls the constructor explicitly ''Calculator(int px, int py)''. The other constructor, ''Calculator()'', is the default one, and if not explicitly called by the code developer, it is automatically called when the object is instantiated.\\
 There can be multiple constructors, and the one executed is selected based on the arguments set.\\ There can be multiple constructors, and the one executed is selected based on the arguments set.\\
 +
 **Destructor**\\ **Destructor**\\
-A destructor is called automatically when an object's lifetime is to end. It allows, i.e. to release resources, disconnect open connections, and, in general, do some cleanup before the object is gone. The destructor function in the example above does nothing and is not obligatory in the code. Destructor name starts with a ~ sign (tilde) and has the same name as a class (or constructor):+A destructor is called automatically when an object's lifetime is to end. It allows, e.g. to release resources, disconnect open connections, and, in general, do some cleanup before the object is gone. The destructor function in the example above does nothing and is not obligatory in the code. Destructor name starts with a ~ sign (tilde) and has the same name as a class (or constructor):
 <code c> <code c>
 ~Calculator(){} //This is dummy destructor ~Calculator(){} //This is dummy destructor
 </code> </code>
 <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> <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>
 +
 **Members**\\ **Members**\\
 Member fields can be of any type. When marked as ''private'' they are accessible only from the code of the constructors, destructor and methods within the class. When ''public'', one can reference them using a "." (dot) operator, as in the case of the structures. When using a pointer to the class instance (object) rather than an instance itself (quite common), a "->" operator works as in the case of structures.\\ Member fields can be of any type. When marked as ''private'' they are accessible only from the code of the constructors, destructor and methods within the class. When ''public'', one can reference them using a "." (dot) operator, as in the case of the structures. When using a pointer to the class instance (object) rather than an instance itself (quite common), a "->" operator works as in the case of structures.\\
 +
 **Methods**\\ **Methods**\\
-A method can have any name other than reserved (i.e. for constructors and destructor). Methods marked as ''public'' are available for the object user and are referenced similarly to member fields ("." and "->" operators). '' private '' methods are not exposed externally; their purpose is to be called from another method internally. Sample use of methods is presented below:+A method can have any name other than reserved (e.g. for constructors and destructor). Methods marked as ''public'' are available for the object user and are referenced similarly to member fields ("." and "->" operators). '' private '' methods are not exposed externally; their purpose is to be called from another method internally. Sample use of methods is presented below:
 <code c> <code c>
   //continuing initialisation above: calc1.x=2, calc1.y=15    //continuing initialisation above: calc1.x=2, calc1.y=15 
Line 127: Line 134:
  
 **Class inheritance**\\ **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 ''Calculator'' class misses some features, such as i.e. subtracting.+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 ''Calculator'' class misses some features, such as subtracting.
 A code below defines a new type ''BetterCalculator'' that inherits from the ''Calculator'' class, using ":" operator: A code below defines a new type ''BetterCalculator'' that inherits from the ''Calculator'' class, using ":" operator:
 <code c> <code c>
Line 143: Line 150:
 Instantiation and use are similar to the presented ones in the previous examples: Instantiation and use are similar to the presented ones in the previous examples:
 <code c> <code c>
-  BetterCalculator calc2=BetterCalculator(10,6); //BetterCalculator->Calculator->x=10, y=6+  BetterCalculator calc2=BetterCalculator(10,6);  
 +                   //BetterCalculator->Calculator->x=10, y=6
   ...   ...
   z = calc2.Sub(); //z=4   z = calc2.Sub(); //z=4
Line 149: Line 157:
                    //class without a need to rewrite it again                    //class without a need to rewrite it again
 </code> </code>
 +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, "::" (double colon), is used in the implementation to refer the code to the definition in the header file.\\
 +The sample header file ''myclass.h'' with the aforementioned ''Calculator'' class is present below. It contains only the class definition but does not contain any implementing code.
 +<code c>
 +#ifndef h_MYCLASS
 +#define h_MYCLASS
 +class Calculator{
 +  public:                       //you can access this part
 +  int x,y;
 +    Calculator();               //Default constructor
 +    Calculator(int px, int py); //Another constructor
 +    ~Calculator();              //This is dummy destructor
 +    int Add();
 +    int Mul();
 +    void setX(int px);
 +    void setY(int py);
 +  private:                      //that part is private, 
 +                                //and you cannot access it      
 +    void clear();
 +};
 +#endif
 +</code>
 +The implementation code refers to the class definition in the header:
 +<code c>
 +#include "myclass.h"
 +
 +Calculator::Calculator() {}
 +Calculator::Calculator(int px, int py) { x=px; y=py; }
 +Calculator::~Calculator(){}
 +int Calculator::Add(){ return x+y;}
 +int Calculator::Mul(){ return x*y; }
 +void Calculator::setX(int px){ x=px; }
 +void Calculator::setY(int py){ y=py; }
 +void Calculator::clear(){ x=0; y=0; }
 +</code>
en/iot-open/introductiontoembeddedprogramming2/cppfundamentals/structuresandclasses.1689086257.txt.gz · Last modified: 2023/07/11 11:37 (external edit)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0