From C to C++


About this Document

License

  This document is Copyright (c) Virgil Mager,
(c) Information Technology Group - www.itgroup.ro
.

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
with no Invariant Sections, no Front-Cover Texts, no Back-Cover Texts.


The 'struct' tag

A C structure tag automatically becomes a type name in C++, i.e. the declaration 'typedef struct {..} TypeName;' is synonimous with 'struct TypeName {..};' C++ Objects

In C++, an *instance* of a structure (or class) is called an 'object', be it a variable, a temporary data passed to / returned from a function, or data allocated on the heap.
The term 'object' can also be used in more general way, such that it designates any entity that has been allocated in memory, except arrarays (an array of objects is not itself an object); under this "extended" convention, even primitive deata types (such as an integer local variable, a float data allocated on the heap, etc) are called objects. In fact, some fundamental syntactical constructs that C++ introduces in relation to structure-based objects are also usable in conjunction with the C++ primitive data types (such as 'int', 'float', 'bool', etc). Expression evaluation

Understanding the mechanim used for expression evaluation is critical for understanding the advanced features of C++, and it requires understanding the functional representation of expressions: any C++ expression containing (or not) inbuilt operators can be re-written in a functional form, no matter that the operators are prefix, infix, or postifx. In the example above, all operators were re-written in a functional form. Based on this format, a conceptual "function evaluator" entity can be thought of as being responsible for evaluating the expression. The evaluation of an expression is now reduced to evaluating its "top-level" function: this process starts with evaluating the "leaf" functions (according to the C++ evaluation order rules), continues with evaluating the functions that have as arguments the results of the leaf functions, and so on all the way to the top-level function. As it can be seen, a fundamental processes involved in evaluating an expression consists of passing 'data objects' between the various functions that represent the expression. There are two "directions" of passing data objects in the functional notation of an expression: the function evaluator tranfers data *to* a function's argument(s) when it invokes the function (e.g. the 'a' and 'b' arguments are tranferred to the second 'SUM' function above), and the function then tranfers its result (i.e. its return value) back *from* the function to the function evaluator in order to continue the evaluation of the "top-level" function (e.g. the result of the second 'SUM' function above is transferred back to the expression evaluator in order to complete the calculation of the top-level 'SUM' function). Passing a data object from the function evaluator to a function argument (i.e. initializing the function argument), and passing a function's result back to the function evaluator, can be performed in two different ways in C++: passing the data 'by value' and passing the data 'by reference'



The 'enum' keyword

In C++ the 'enum' keyword declares a new data type; a variable of an enum type is nolonger considered (like in C) an integer value. Namespaces

Just like in C, new un-named namespaces are generally generated with each '{' and end with the corresponding closing '}'. Once an entity is declared (and possibly also defined) inside a namespace it cannot be accessed directly from *outside* the scope of the respective namespace, but it can be directly referenced from within the scope of the namespace where it is declared. Also, the scope of a namespace contains the scopes of all namespaces declared inside it.
An entity declared within a namespace will "hide" an entity with the same name in any namespace that (directly or indirectly) contains the namespace where the entity is declared. As opposed to the C programming language where namespaces are anonymous, C++ allows declaring *named* namespaces via a dedicated 'namespace' statement, i.e. a named namespace is a notational wrapper over a set of entities (variables, types, enums, functions, etc). Once an entity 'myEntity' is declared inside a namespace 'MyNamespace' it will be impossible to access that entity directly from outside the namespace where it was declared, but it will still be accessible from outside by using the syntax 'MyNamespace::myEntity'. A keyword that complements 'namespace' is 'using':

Methods

Apart from allowing the declaration of data fields inside structures (like in C), C++ also allows including function declarations inside structures; these functions are also known as "methods" (associated with the structure in which they are declared) Such functions that are declared inside objects are *conceptually very different* from "normal" functions: The 'const' modifier

In C++, a 'const object' is an object instance that can be initialized but cannot be modified, and the C++ lexicon includes the 'const' modifier keyword for explicitly declaring 'const' objects. The only allowed ways to initialize an object declared as 'const' are when such an object is a function argument and it receives an initial value at a function call, or via an explicit initialization value directly in the object's declaration.

The 'const' modifier can be used in conjunction with variables and functions in the following ways: Function overloading Operator overloading

in both C and C++ the predefined operators are actually implemented as functions (the fact that they can be used with the "usual" arithmetic operators syntax is just a convenience implemented by the language). Based on the function overloading facilities, in C++ operators can also be overloaded (just like an "ordinary" function).
There are two ways to overload an operator: inside and outside an object. Following is a description for the syntax used in the two cases. Creating and Destroying Objects

The C++ language encourages the programmer to use the "object oriented approach" (see also the Object Oriented Programming paradigm section above), where the 'object types' are expressed via structures or classes. This section introduces C++ objects based only on structures, and 'object type' and 'structure' will be used interchangeably.
The (very few) differences that exist between structures and classes will be addressed in the 'Classes' section below.
Derivation
C++ classes

Essentially, classes are *very* similar to structures (with all the added C++ functionality like member functions, etc), but offer three levels of "explicit protection" for their members (variables and functions), and three types of derivation.
Automatic type conversions

C++ extends the automatic type conversions inherited from C, e.g. the inbuilt automatic conversions between primitive numeric values, with a more complex algorithm that addresses C++ specific features such as object constructors, the objects' conversion operators, and the ability to overload functions. The basic rules for automatic type conversions in C++ are:
Explicit casts

Apart from the C cast syntax '(NewType)myData', C++ introduces several new types of casts while also strongly recommending against the use of the old-style C casts in new C++ programs. The new C++ casts are:
Exceptions

C++ encourages the algorithm designer to separate two distinct "program flows" when writing the code for a function (and/or method): the "normal" execution flow, and the "exceptional" execution flow. Exactly *what* constitutes the "normal" and the "exceptional" execution flows within a program is up to the programmer to decide, but once this decision has been made the C++ language assists the programmer with clearly separating these two execution flows via the special-purpose 'try/throw/catch' laguage construct.


A brief introcution to templates

Templates are a way to allow *compile-time* parameterization for classes and/or functions. If the C++ language features as described in the previous paragraphs allow for run-time parameters to be passed to functions, templates extend this feature to compile-time parameters which can be both values *and type names*.