C++ PROGRAMMING

C++ Programming

Article by:
Date Published:
Last Modified:

Child Pages

  • A Brief History Of C++
  • Auto (Specifier)
  • Boost Libraries
  • C++ Callbacks (and giving member functions to C-style callbacks)
  • C++ On Embedded Systems
  • Classes
  • Clocks And Timing
  • Code Checkers
  • Const Correctness
  • Containers
  • Exceptions
  • Inheritance
  • Input And Output
  • Linux Bash Commands For C++
  • Magic Statics
  • OpenMP Tutorial
  • Operator Overloading
  • Qt
  • References
  • Smart Pointers
  • Special Casts
  • Streams
  • Strings
  • Threading
  • Type Conversion
  • Unit Testing And Mocking
  • Virtual Methods
  • Warning And Error Message Help
  • Overview

    This page covers C++ programming and it’s use in embedded programming.

    C++ started out as a preprocessor for C, before later developing into it’s own language.

    One of my favourite quotes:

    C makes it easy to shoot yourself in the foot…C++ makes it harder, but when you do, it blows your whole leg off. - Bjame Stroustrup

    Benefits Over C

    • Namespaces
    • Classes (which can be viewed as fancy and more powerful structs!)
    • Function overloading (differing number of input variables for the same function name)
    • Operator overloading (e.g. a + sign could do whatever you want it to do, not necessarily add. Good for making things like imaginary number and fixed-point arithmetic intuitive).
    • Stricter variable type conversions, resulting in less type related errors (with more cast keywords such as static_cast<>() , dynamic_cast<>() e.t.c)
    • High-level programming (this can also be a disadvantage, due to loss in transparency)
    • Enumeration constants can have the same name (as long as they are in different namespaces/classes).
    • More system libraries. C++ has all of the standard C libraries plus an extended set of useful libraries.
    • No implicit conversion between void* and char* , this has to be explicitly defined
    • You get a constructor which is called when an object is created. In many cases this can replace remembering to call the traditional Init() function.
    • The ability to quickly change a variable/function from private to public (useful for debugging/testing).
    • A full explanation of the source code from just looking at the header file (the class definition includes private objects as well as public).
    • Parameters lists for creating constructors

    Disadvantages Over C

    • Not as much support for embedded systems. Any self-respecting embedded system has a compiler for C. However, C++ compilers are less common. Saying that, many of the most popular microcontrollers such as the ATmega, 8-bit Arduino’s (which uses an ATmega anyway) support C++. And some of those that don’t can be hacked to compile C++ (e.g. PSoC 5).
    • Less transparent, loss of exact control over what the compiler generates
    • More memory issues, greater code footprint (potentially)
    • Function pointers no longer work the same way when they point to a function in a class (aka point to a member function)
    • Non-static class variables can’t be initialised at the same time as the declaration (they have to be initialised either in the constructor or a purpose made Init() function.
    • It’s more complicated! Every heard of a protected abstract virtual base pure virtual private destructor? Well, in C++, they do exist!

    Mixing C With C++

    C code can be mixed (aka compiled) with/alongside C++ code. One important thing to note that C can be compiled from inside C++ code, but C++ code cannot be compiled from C code. This means that the file that includes main() must be compiled with C++, but main can call external C functions.

    Name Mangling

    Name mangling is a technique used by C++ compilers to distinguish overloaded functions of the same name. The compiler adds some seemingly unintelligable characters to the end of overloaded functions (these characters are related to the input variables). C compilers do not do this as the C standard does not support overloaded functions (even though it looks like it, printf(string, variable1, variable2, ...) is not overloaded!). When cross-compiling, this has to be taken into consideration.

    Compilers

    Most embedded C++ compilers use GCC. The main competitor to the GCC compiler is Clang, however it is not as common in embedded environments (I have never personally used Clang to compile for an embedded application).

    See the Linux Bash Commands For C++ page for a quickstart C++ guide for Linux.

    Constructors

    There is a syntax ambiguity in C++ which normally appears when you are trying to create an object of a particular type, and using the default constructor. It is called the “Most Vexing Parse”.

    Constructors cannot be declared static, as it makes sense that they only belong to an object of that class type. If you want to initialise static member variables, you do this in the normal C way, outside of the class definition.

    Constructors can take parameter lists, which along with constructors, is a new concept that is not present in C.

    Namespaces

    Namespaces give you the ability to wrap functions and variables into groups. Calling functions or accessing variables within a namespace requires you to use the :: syntax, or by using the using namespace blah syntax (see the code examples below).

    This removes the need for the common C convention of prefixing all functions with the name of the file they are in (for example, files in Uart.c would be called things like Uart_PutString() and Uart_GetChar().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    namespace Uart {
        void PutString(char *string) {
            // code
        }
    
        char GetChar() {
            // code
        }
    }
    
    // We are outside the Uart namespace. To call these functions, we need to prepend the function calls with the namespace name and the `::` syntax
    Uart::PutString("blah");
    char char1 = Uart::GetChar();
    
    // However, we are able to drop the "Uart::" bit if we use the keyword "using"
    using namespace Uart;
    // Now we can just type
    PutString("blah");
    // Note that this should only be done for standard or very widely used libraries, as it reduces the information
    // to the code reader and can cause ambiguities if there are functions with the same name.
    

    Qualifiers

    static

    Inside a class: When static is used inside a class, it means that a new version of the function/variable will not be created for each instance of the class. All static objects are shared with all instances of the class, and static variables exist from start-up. For this reason, there is no this object available for any static class function, and so it can’t access the classes non-static members (if you think about this, it makes sense). It also means that creating multiple objects of a class with static members has interesting effects, and you have to consider corruption and thread safety when doing so.

    You can’t declare a whole class as static, as you can in C#. All that a static class in C# does if force you to make all of it’s members static also, which you can do anyway in C++.

    Static can be a good way to get around the annoying “pointer to non-static member function” error you get when mixing C++ with C (especially in embedded situations). This is because you CAN take a pointer to a static member function. Just remember about the other implications it has!

    Forward Declarations

    Forward declarations can be used to resolve circular dependencies of pointers to classes (but only pointers, and not circular dependencies of objects, these are illegal).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    namespace NsB {
        // Forward declaration
        class B;
    }
    
    namespace NsA {
        class A {
            // This is legal since there
            // is a forward declaration above
            B* b;
        }
    }
    

    Note that you cannot write a forward declaration for a class in a different namespace using the <namespace name>::<class name> syntax, you have to fully "open" the namespace using the namespace <namespace name> { class <class name>; } syntax, as shown below.

    1
    2
    3
    4
    5
    6
    7
    8
    
    // Illegal forward declaration
    // (will get "does not name a type" error)
    class NsB::B;
    
    // Legal forward declaration
    namespace NsB {
        class B;
    }
    

    External Resources

    C And C++ In 5 Days is a good PDF which provides help for both C and C++.

    If you want to read up on why C++ is what it is, and the thoughts/idea behind one it’s principle designers, read A History Of C++: 1979-1991 by Bjarne Stroustrup


    Authors

    Geoffrey Hunter

    Dude making stuff.

    Creative Commons License
    This work is licensed under a Creative Commons Attribution 4.0 International License .

    Tags

      comments powered by Disqus