C++ is a remarkably powerful systems-programming language, combining multiple programming paradigms – Procedural, Object Oriented and Generic – with a small, highly-efficient run-time environment. This makes it a strong candidate for building complex high-performance embedded systems.
The C++11 standard marked a fundamental change to the C++ language, introducing new idioms and more effective ways to build systems. This new style of programming is referred to as ‘Modern C++’.
This practical, hands-on course introduces the C++ language for use on resource-constrained, real-time embedded applications.
The course highlights areas of concern for real-time and embedded development. The focus is on developing effective, maintainable and efficient C++ programs.
The course covers C++11, C++14 and C++17 and where relevant refers to C++20.
Overview:
A five-day course that provides a practical overview of C++ focusing on developing object-oriented programs in an embedded, real-time environment.
Course objectives:
- To provide a solid understanding of the essentials of the C++ programming language.
 - To give you practical experience of writing Modern C++ for resource-constrained real-time and embedded systems.
 - To give you the confidence to apply these new concepts to your next project.
 
Delegates will learn:
- Modern C++ syntax and semantics and idioms
 - Using C++ for hardware manipulation
 - The Application Binary Interface (ABI) and memory model of C++
 - Idioms and patterns for building effective C++ programs
 
Pre-requisites:
- A strong working knowledge of C
 - Embedded development skills are useful, but not essential
 
Who should attend:
This course is aimed at C programmers who are moving to C++ for their embedded development.
Duration:
- Five days
 
Course materials:
- Delegate manual
 - Delegate workbook
 
Course workshop:
Attendees perform hands-on embedded programming, during course practicals. Approximately 50% of the course is given over to practical work.
The board targeted is an ARM Cortex-M based MCU which gives attendees a real sense of embedded application development.
Program structure
- "Hello World!"
 - The build process
 - Object files
 - Linking Activities
 
Stream I/O
- C++ stream I/O objects
 - Stream modifiers
 
The C++ object model
- Objects and types
 - Brace initialisation
 - Object visibility scope
 - Object lifetime
 
Constants
- Literals
 - Compile-time constant expressions
 - Enum classes
 
Pointers
- Dynamic objects
 - The value of an ‘empty’ pointer
 - Pointers and const
 
Hardware manipulation
- Memory-mapped registers are accessed via pointers
 - volatile objects
 - Bitwise Operators
 - General Purpose Input / Output (GPIO)
 
Structures
- User-defined types
 - Packing
 - Performance implications of packing
 
Arrays
- Containers
 - The iterator model
 - Range-for statement
 - Applying algorithms to arrays – filling and sorting
 
Functions
- The 'One Declaration Rule'
 - How function arguments are passed
 - The overheads of pass-by-value
 - Pass-by-reference
 - std::tuple represents a general n-tuple
 - Function overloading
 - Function inlining
 
Structuring code
- Separating Interface and Implementation
 - Compilation Dependencies
 - Using the __cplusplus macro
 
Namespaces
- Defining functions within a namespace
 - Ambiguity when accessing namespace members
 
Principles of Object Oriented Design
- Coupling
 - Encapsulation
 - Cohesion
 - The Single Responsibility Principle
 - Abstraction
 
User-defined types
- Creating new types
 - Access specifiers
 - 'this' pointer
 
Initialising objects
- Non-Static Data Member Initializers (NSDMIs)
 - The compiler-supplied default constructor
 - The class destructor
 
Objects and functions
- Pass-by-value
 - Explicit constructors
 - Disabling pass-by-value
 - Disabling copying
 - Return Value Optimisation (RVO)
 - 'Copy elision'
 
Static
- The static storage specifier
 - Static member variables
 - Static member functions
 
Object-based I/O
- An Object-Oriented approach to I/O
 - Using a struct for I/O device access
 - Nesting a structure overlay in a class
 
Operator overloading
- Problem domain types
 - Overloading the stream operator
 - Conversions to other user-defined types
 
Building composite objects
- Composite aggregation
 - Overriding default initialisers
 - The composite object on the stack...
 
Connecting objects
- Connected objects form a system
 - Forming the Association (Client-Server)
 - Bi-directional associations…
 - Friend functions
 - Forward references to namespace elements
 
Creating Substitutable Objects
- Specialisation
 - Inheritance
 - Overriding base class behaviour
 - The 'protected interface'
 - The Liskov Substitution Principle
 - Late binding (of polymorphic operations)
 - Dynamic binding
 
Abstract Base Classes
- An abstract class
 - Extending derived classes
 - Safely accessing the extended interface
 
Realising Interfaces
- The Dependency Inversion Principle
 - Provided and Required Interfaces
 - The Interface Segregation Principle
 - Cross-casting
 
Dynamic objects
- Memory model
 - std::unique_ptr allows single ownership
 - std::shared_ptr is reference-counted
 - std::weak_ptr
 - Resolving circular dependency issues
 
Dynamic containers
- Sequence containers
 - std::vector is a dynamically-resizable array
 - std::list is a doubly-linked list
 - Key-value containers – std::pair
 - Sorted containers
 - Containers and memory allocation
 
Callable objects
- Function objects
 - Lambdas
 - Under the hood
 - Using std::function for call-back
 - Containers of callable objects
 
Initializer lists
- std::initializer_list
 - initializer_list overload rules
 
Template functions
- Generic programming
 - Function templates
 - Overloading with template functions
 
Template classes
- Class templates
 - Lazy instantiation
 - Member Functions of Class Templates