S R T B H P N

C++ and its Environment

Topics with selected details


A summary of C++ topics, with links to many of the most important details.

Topics:

C++ Language
A large, but elegant, programming lanaguage that compiles to native code. It favors enabling users over protecting them.
Historical Context C++ derives most of its language elements and function structure from the C programming language, which in turn, inherited those things from Algol, a European language. It derives its notions of class from SmallTalk. language relationships diagram
Classes A class is a language construct that binds together member functions and data, providing access to users only to public member functions, not to its data. This encapsulation enables the class to make strong guarantees about validity of its data. This class was designed to hold file information, including both file name and path. The intent is to hold any given file name only once, even if the file has copies in several directories, and to hold each path name only once. That is done using a unique arrangement of STL containers.
class DataStore
{
public:
  using Date = std::string;
  using Path = std::string;
  using Paths = std::set < Path > ;
  using PathIter = Paths::iterator;
  using ListOfIters = std::list < PathIter > ;
  using Item = std::pair<PathIter, Date>;
  using ListOfItems = std::list<Item>;
  using File = std::string;
  using Store = std::map < File, ListOfItems >;
  using iterator = Store::iterator;
  using PathCollection = std::vector < Path > ;

  void save(const std::string& filespec);
  void save(const std::string& filename, const std::string& path);
  PathCollection getPaths(const File& file);
  size_t numberOfFiles();
  size_t numberOfPaths();
  iterator begin() { return store.begin(); }
  iterator end() { return store.end(); }
private:
  Store store;
  Paths paths;
};

inline size_t DataStore::numberOfFiles() { return store.size(); }

inline size_t DataStore::numberOfPaths() { return paths.size(); }

DesignNote-CppClasses.html - class structure,
Value Types A value type provides copying, assignment, and move operations that allow instances of the type to behave like built-in types. ValueType, ValueType.pdf
Functors A functor is a class that defines operator(). That means that instances can be "invoked" like this:
  class AFunctor {
  public:
    AFunctor(const X& x) : x_(x) {}
    void operator()(const Y& y) { /* do something useful to x_, using y */ }
    X value() { return x_; }
  private:
    X x_;
  };

  AFunctor func;
  Y y;
  func(y);          // syntactically looks like a function call
  func.operator(y); // equivalent to the statement above
            
Functors are used in CallableObjects code demo in CppBasicDemos repository.
Lambdas A lambda is an anonymous callable object that can be passed to, and returned from other functions. A lambda is really a short-cut to define a functor. A very useful feature of lambdas is their capture semantics. They can store data defined in their local scope, to be used later when they are invoked.
  std::function makeLambda(const std::string& msg)
  {
    // [=] implies capture by value, [&] implies capture by reference
  
    std::function fun = [=]()
    {
      std::cout << "\n  displaying captured data: " << msg;
    };
    return fun;
  }

  // in some other scope

  std::function myFun = makeLambda("hello CSE687-OnLine");
  std::cout << "\n  using Lambda: " << myFun() << "\n";
              
CodeSnap-LambdaCapture.cpp.html
Callable Objects A callable object is any C++ construct that can be invoked using parentheses, callable(...). Function pointers, functors, and lambdas are all callable objects. Here's a function that accepts and invokes any callable object that takes no arguments:
  template<typename T>
  void invoker(T& callable)  // callable could be a lamda with captured data
  {
    callable();  // use captured data instead of function arguments
  }
            
CppBasicDemos Repository holds Callable Objects demo code
Class Relationships Classes have four relationships:
  • Inheritance:
    A derived class inherits all it's base's members. Non-virtual base functions should not be redefined in the derived class. Virtual member functions may be redefined in the derived class. Pure virtual functions must be redefined.
  • Composition:
    Instances declared as class data members are composed by the class, creating a strong owning relationship. Composed members are always constructed when the composer is constructed, and destroyed when the composer is destroyed.
  • Aggregation:
    A class aggregates a data member when it holds a pointer to the member instance on the native heap. Creation of an instance of some type as local data in a member function is also considered to be aggregation. Aggregated instances are owned by the aggregator, but this is a weaker relationship than composition, as the aggregated instances do not exist until code in the aggregator creates them.
  • Using:
    A class uses an instance of some other class when it is passed the instance to one of its public member funtions by reference. Using is a non-owning relationship and your classes should respect the owning code by doing nothing to invalidate the used instance. Passing an instance by value to a member function is really aggregation, because the receiving class creates and uses its own copy.
These four relationships are all that are needed to build Object Oriented programs. DesignNote-CppClassRelationships.html, CodeSnap-CompoundObjects.cpp.html
Compound Objects Compound objects are instances of classes that use inheritance, composition, and aggregation of other classes to carry out their mission. We need to be careful, especially with initialization, to ensure they operate as expected. Here is a good example of the initialization and use of compound objects. CompoundObjects.html Repository
Templates Templates are compile time constructs that allow us to avoid writing a lot of nearly identical code for classes that could sensibly use any of several concrete types, perhaps as arguments to member functions or as instances of member data. Containers are a good example. Here is an example from CppBlockingQueue repository.
template <typename T>
class BlockingQueue {
public:
  BlockingQueue() {}
  BlockingQueue(BlockingQueue<T>&& bq);
  BlockingQueue<T>& operator=(BlockingQueue<T>&& bq);
  BlockingQueue(const BlockingQueue<T>&) = delete;
  BlockingQueue<T>& operator=(const BlockingQueue<T>&) = delete;
  T deQ();
  void enQ(const T& t);
  T& front();
  void clear();
  size_t size();
private:
  std::queue<T> q_;
  std::mutex mtx_;
  std::condition_variable cv_;
};
              
T is a type that isn't specified until an application using the queue is compiled, so it will hold strings or messages or whatever the application needs without changing any of the BlockingQueue code. Templates are also useful for building functions that accept callable objects, i.e., function pointers, functors, or lambdas. We use template functions to accept instances of any of these distinct types. Thread constructors are a good example. Templates.html, CodeSnap-Templates.h.html Here are a few interesting examples of template use:
Exceptions Exceptions are a language defined mechanism for handling errors. Exception handling uses instances of std::exception and the key words throw, try, and catch. You should always throw exceptions by value and catch them by reference. except.pdf
Namespaces A namespace defines a compile-time scope used to distinguish between two or more type or function names with the same value but that have distinct definitions in separate places in code for a single compilation unit. A namespace extends the name of a type, for example, by prepending the type name with the namespace name, i.e., MyNamespace::MyType. Namespaces.pdf
Dark Corners The C++ language has a surprisingly short list of dark corners, e.g., compilable constructs that may cause subtle errors. Most of these have to do with causing Liskov Substitution to fail by improper overloading, overriding, or failing to provide virtual destructors. Evils.pdf
Standard Libraries The C++ language uses a very well engineered set of standard libraries for I/O, managing data, and using threads, and much more. Each new C++ standard introduces new libraries or new library features. We've focused on these:
Streams Library A collection of libraries for stream-based I/O, for the console, files, and in-memory strings. Streams use the insertion operator<<(...) and extraction operator>>(...) to build composable input and output operations. Here is code and a brief presentation about the structure of the streams library. Almost all of the capabilities of the streams library are demonstrated in the code:
  • formating console I/O
  • reading and writing files
  • reading and writing in-memory strings
  • using filebufs to stream data
  • reading and writing to the same filebuf
Streams Library Reference
STL Library The Standard Template Library is a subset of the C++ standard libraries. It provides a large set of containers, each with a defined iterator type, and a set of algorithms designed to operate on the containers. All of the containers are endowed with correct construction, copy, and destruction semantics. Here is a presentation of the structure and top-level properties of the STL: STL.pdf STL Library Reference
Threads Library Threads library, introduced in the C++11 standardization, contains classes for threads, locks of various kinds, atomics, condition variables, and futures. Futures are interesting because they support returning values computed by child threads, blocking until the result is ready. Here are some useful code demos and resources for programs that use threads: ThreadsWinAndCpp11.pdf, CppThreads.html, Threads Library Reference
Other C++ standard libraries
Custom Libraries These libraries are code that I've written, and hosted in these repositories. They supplement the C++ Standard Libraries, providing functionality that does not exist there (as of C++11).
FileSystem A library for managing and querying Windows directories and their objects. It was written entirely in C++11, using the Win32 API. It has classes File, FileInfo, Directory, and Path, that are modeled after the very well-engineered .Net System.IO library. FileSystem.html
Sockets A library that provides an abstraction above the Windows sockets library, making many of its operations more user friendly. It provides classes: Socket, SocketConnecter, SocketListener, and SocketSystem. Sockets.html
CppGraph A small C++ library for building directed graphs, with classes Vertex, Edge, and Graph. The library supports Depth First Search traversal and the application of operations on each node during traversal. CppGraph.html
XmlDocument A library for constructing XML strings and files, and creating a Document Object Model (DOM) instance from well formed XML strings and files. XmlDocument.html
Threads A thread is a block of processing instructions, defined by a function passed to the operating system (OS), that executes in a processor core, and is started and stopped by the OS. A thread often runs in an environment containing many other threads that are sequenced in short time-slices by the OS to behave like concurrent processing. A thread may run continuously in a core if there are no other threads contending for that resource. The C++ Standard Library provides the libraries: thread and atomic to support concurrency. Win32AndCpp11Threads.pdf, CppThreads.html, CppBlockingQueue.html
Sockets An interface for network communication provided by a low-level Windows library. The sockets we discuss are all stream-oriented, reading and writing sequences of bytes. Stream-oriented means that sockets do not provide you with a message structure. If you need that you will have to provide it. In order to communicate these sockets have to be connected. To connect, your code needs, on one end of the channel, a connecter socket and, on the other end, a socket listener, to listen for, and establish a connected channel. The Sockets library, in these repositories, provides good support for building programs using network communication. Win32Sockets.pdf, Sockets.html, CppCommWithFileXfer.html
Graphical User Interfaces The standard C++ libraries do not provide any support for Graphical User Interfaces. But it is fairly easy to provide one for a native C++ application by using a C#-based Windows Presentation Foundation (WPF) project that communicates with the application through a C++\CLI shim. The WPF-Interop demo is a simple example of how to do this. WPF-Interop demo code
Simple example of C# GUI interoperating with native C++ code via C++\CLI Diff_WPF
WPF GUI spawning a Windows program. Background Information:
WPF Windows Presentation Foundation (WPF)
A Graphical User Interface (GUI) framework that:
  • Builds interface windows using a custom XML markup, called XAML, and C# or C++\CLE event handlers.
  • Layout model is similar to HTML.
  • Provides pervasive dependency relationships between graphical elements and bubbling of events.
  • Supports very complete designer control over appearance and behavior of each window view.
  • Runs only on Windows, as a desktop application, and in the Mono environment on Linux.
C++\CLI C++\CLI
A .Net managed language that runs in a Common Language Runtime (CLR) virtual machine and stores its instances in a managed heap, providing garbage collection, exception handling, and reflection services. C++\CLI code interoperates directly with native C++ code. C++\CLI code and native C++ may be placed in the same file.