2 C++ programming basics – Computational Technologies

Victor S. Borisov and Petr N. Vabishchevich

2 C++ programming basics

Abstract: New features of the C++ programming language in comparison with C are associated with the support of abstract data types and object-oriented programming. A class is the most important concept of C++.

2.1 Enhanced features

Below we consider some new possibilities of C++ (in comparison with C not connected with the paradigm of object-oriented programming.

2.1.1 Keywords

The list of keywords of C (page 3) is extended in C++.The following keywords are reserved in addition to C:

2.1.2 Declaration of variables within blocks

In C, a declaration of local variables within a block is placed at the beginning of the block, before the first executable statement. As for C++, variables can be declared anywhere within a block before their use. The declaration and use of a loop counter is shown in the following example.

Listing 2.1.

The local variables s1, s2, i are not available outside the loop.

2.1.3 Scope resolution operator

The scope resolution operator : : provides access from a block to a global variable which has the same name as a local variable. For example,

Listing 2.2.

The output is

 

global i = 1, local i = 2

2.1.4 Default arguments

In C++, arguments can be omitted in function calls. In this case, default values are used for the omitted arguments. Default values are defined in a function prototype. If a value of an argument is omitted, then the values of all the following parameters must also be omitted.

Listing 2.3.

2.1.5 Boolean type

In C, there is no specific logical type; integer variables are used instead. The true value is associated with any nonzero integer; false corresponds to zero.

C++ directly introduces the boolean type bool. A boolean variable takes two values: false and true.

An example of boolean variables declaration:

2.1.6 Dynamic memory

In C++, an object can be created (declared) in any place where it needs to be used. The operators new and delete are used for this. The following example illustrates a typical situation of dynamic creation of an array.

Listing 2.4.

Memory allocation is performed by the statement new int [ n ], whereas deallocation is carried out via delete [ ] a.

In C, the direct application of library functions malloc, calloc, and free is required. For the above-mentioned example, the header file stdlib. h of the C standard library must be attached, and two lines must be changed.

Listing 2.5.

2.2 Classes

C++ gives the programmer the opportunity to expand independently the capabilities of the programming language by creating his own data type required for solving specific problems. A class is a collection of related variables and associated functions intended to work with variables. Classes in C++ are an advanced version of structures (struct) in C.

2.2.1 Creating a class

A class declaration defines a new data type. A class is logical abstraction, and an object is an instantiation (a copy of class). A declaration of a class is similar to a declaration of structure.

An object list allows the declaration of the class objects and can be absent.

Each class contains data (data members) and a collection of functions (methods) to handle this data. Declarations can include both methods and data declarations.

A class definition includes access specifiers besides declarations of data and functions. Access specifiers specify scope rules (visibility) for members of the class:

  • – private – members are visible only within their class and cannot be used outside;
  • – public – members are visible for both members of the class and the outside code;
  • – protected – members are visible for other members and children of the class (in inheritance).

Encapsulating in object-oriented programming is the hiding of class realization details. Using an access specifier, a class introduces another scope besides a file, function, block, function prototype.

By default, methods and data declared in a class are private and accessible only with methods of this class. An access specifier extends its functioning up to the next specifier or the end of the class definition.

This is the class of complex numbers.

Listing 2.6.

A complex number consists of real and image parts. In this case, real and image are data members of the class. Also, the method module is defined to calculate the module of a complex number.

In C++, a structure is a class defined by the keyword struct. The main difference between structures and classes is that all members of a structure by default are public.

2.2.2 Methods

The methods of a class can be inside or outside a class declaration. In the first case, a compiler tries to create an inline function whose code will be placed in the point of a method call. If method calls are time-consuming, inline functions can increase execution efficiency by increasing the code size.

For instance, the calculation of a complex number argument can be implemented in the class Complex as an inline function.

Listing 2.7.

A definition of methods outside a class declaration does not differ from a definition of usual functions except for the requirement that the name of the class and the scope resolution operator : : must be before the name of the function.

Listing 2.8.

2.2.3 Objects of a class

After a definition of a class and its behavior, the class name is used as the name of any data type; for example, int, float. Complex numbers can be defined as follows:

Listing 2.9.

The declared variables c1, c2, c3 are the objects of the class Complex. An object supports the call of member functions of their class by using the operator . (dot).

Listing 2.10.

A pointer to an object can be defined in C++ as for any other variable. The operators new and delete are employed for dynamic creation and deletion of objects. If the access to an object is implemented by a pointer, the operator –> is used instead of the operator . (dot).

Listing 2.11.

2.2.4 Constructors and destructors

After an object is created, all its data must be assigned values. In C++, the initialization and deletion of objects can be performed by constructors and destructors, respectively. A constructor is a special block of instructions called during object creation and designed to initialize an object. A constructor has the same name as the class and returns nothing. A class can have several constructors with different sets of arguments.

Listing 2.12.

If a constructor is not defined, a compiler generates a default constructor that has no parameter and does nothing. If a class has other constructors, a default constructor has to be defined directly.

A constructor is called when an object is created.

Listing 2.13.

A destructor is called every time an object is destroyed. The destructor has the same name as the constructor, but it is preceded by a ~. A destructor has no arguments and returns nothing.

Listing 2.14.

A compiler creates a destructor if it is not directly defined. When a function, where a local object was created, completes its work, a destructor of an object is automatically called. A direct call of the destructor is not required. If an object was created using new, then delete is used to call the destructor.

2.3 Function and operator overloading

Function overloading is the process of using the same name for two or more functions. Function and operator overloading illustrates the polymorphism of C++, i.e. one interface, many methods.

2.3.1 Function overloading

Several functions with the same name can be used in C++; each of them can perform different actions and must have different lists of parameters. This capability is convenient to use for performing actions with same meaning on objects of various types.

A simple example is the overloaded function for printing values with types int, double, and char*.

Listing 2.15.

2.3.2 Operator overloading

In C++, overloading is also permitted for operators. Thus, operators can be used not only for built-in types, but also for classes.

Overloaded operators exist in the language itself. For example, the addition operator works with different types int, float, and double, and not only with them. Let @ be some operator of C++ (apart from .. * : : ? :). Then it is enough to define a function with the name operator@ and necessary arguments for this function to perform the necessary actions. These actions are equivalent.

Overloading of the addition operator in the class of complex numbers is given as follows.

Listing 2.16.

In this example, the keyword const provides immutability of the argument and object.

2.3.3 Operator overloading with friend functions

Access specifiers directly indicate whether functions outside of the defined class can access its members or not. The friendship concept provides for a certain function or class the access to elements of a class, which are specified as private or protected. To declare a function as a friend of a class, the keyword friend is put before the function prototype in the class definition.

In the following we use friend functions for overloading the multiplication operator in the work with complex numbers.

Listing 2.17.

2.4 Inheritance

The reuse of high-quality software saves time and effort in the development of new programs. Inheritance is considered to be the main approach to reuse software. New classes are created from already existing classes by taking their attributes and functions and adding new features.

2.4.1 Concept of inheritance

In the creation of a new class, instead of writing completely new data-members and methods we can declare that the new class is an inheritor of an earlier defined class (the base class). The new class is called a derived class. In turn, any derived class can serve as the base class for subsequent classes, i.e. we create hierarchical classifications. We speak of simple inheritance if a new class is derived from one base class, and multiple inheritance when a new class is derived by several base classes.

A derived class adds its own data members and functions, and, in this sense, a derived class is richer than the base class. On the other hand, a derived class is more narrow than its base class and operates with a smaller group of objects. Each object of a derived class is also an object of the corresponding base class.

The idea of inheriting existing collections of classes by new classes provides the basis for the hierarchical organization of current software. Individual collections of classes are developed using various widespread libraries available for use. Within the concept of component-based programming, software is designed from the standard repeatedly-used components.

2.4.2 Protected elements

In defining base classes, we may observe elements declared as public, private, and protected. A derived class can use public elements of the base class just as these elements are defined in the derived class. At the same time, the derived class cannot directly work with the private elements of the base class. To use such elements, the derived class must have some interface functions.

Protected elements of the base class stand at an intermediate position between private and public elements. If an element is protected, objects of the derived class can directly apply to the element, as it is public. Direct access to protected elements is impossible for other parts of a program.

2.4.3 Example: a point and circle

As an example of inheritance, we consider the class of points on a plane (the base class) and the class of circles (the derived class).

Listing 2.18.

The class Circle can be used as the base for describing such geometric objects as a cone or cylinder. Thereby, the element radius is declared to be protected.

2.4.4 Virtual functions

A virtual function in C++ is a function that can be redefined in derived classes; a specific realization of this function for call is defined during execution.

Derived classes can redefine a virtual function of the base class or not redefine it. Types of arguments, their number and a returned value type of inherited class function must be the same as for the function of the base class. A virtual function is defined using the keyword virtual in a function declaration.

For example, the virtual function print can be used for the considered classes Point and Circle.

Listing 2.19.

Listing 2.20.

The output of the program is

Virtual functions realize such an important feature of C++ as polymorphism. Polymorphism is the ability for objects of different classes which are associated by inheritance to react differently while calling the same function.

2.5 Input/output

A part of the C++ standard library is the iostream library, which provides a set of features to perform input/output operations. This library supports input/output of data from/to files for built-in data types. Within the concept of object-oriented programming, using one’s own classes, it is possible to extend this library in order to read and write new data types.

2.5.1 Output to streams

To use the iostream library, it is necessary to include the header file

The support of input operations is provided by the class istream; the support of output operations is provided by the class ostream. The derived class of these base classes of iostream supports bidirectional input/output.

In the library iostream, the following streams are defined:

  • – cin – the object of the class istream that corresponds to the standard input (keyboard);
  • – cout – the object of the class ostream that performs the standard output (display);
  • – cerr – the object of the class ostream that implements the standard output of errors.

The class ostream ensures, first of all, input of data of the standard types using the overloaded operator «. This operator is overloaded to output data with built-in types and strings.

Listing 2.21.

The output of the program is

In this example, the overloaded operator « is employed in the concatenated form. The pass to the new line is performed by using both the escape sequence \n and the manipulator endl (the end of a line). The manipulator endl leads also to an output buffer reset.

The namespace std is used in the C++ standard library (in our example, using namespace std;). omit the direct declaration of the namespace, std: : cout and std : : endl need to be used instead of cout and endl, respectively.

2.5.2 Input into a stream

The overloaded operator » is employed to input data. The program to output the multiplication of two entered simple numbers is given below.

Listing 2.22.

Output of the program execution:

2.5.3 Overloading of input/output operators

If we want our class to support input/output operations, then the operators « and >> need to be overloaded. Input and output of a complex number on the basis of overloading of << and >> is shown below.

Listing 2.23.

The output is as follows:

2.5.4 Formatted input/output

Problems of formatting in C++ are resolved by the functions setf, unsetf, and flags of the class ios. The second possibility is associated with the use of manipulators (the header file iomanip). We can assign a width of input/output fields, output data with alignment, output integer numbers in decimal, octal, and hexadecimal forms, output floating numbers with different precision, and so on.

The function flags must assign the value that installs all flags (the type long). The function setf is intended to change one or more flags (the operations is employed to repeat) for the current state of the format. The function unsetf is used to reset a flag (flags). Similar problems are resolved by applying manipulators setiosflags and resetiosflags.

Listing 2.24.

The output of the program is as follows:

2.5.5 Reading/writing from/into files

To work with files in C++, it is necessary to include the header file fstream:

To read data from a file, objects of the class ifstream are used; to write data into a file, objects of the class ofstream is applied. The class f stream is employed to read and write. Files are opened by creating objects of these classes. A constructor of an object has two arguments: a file name and an opening mode. For instance, for the object of stream, the opening mode can be ios : : out to output data without modification to a file.

Table 2.1. Opening mode.

Parameter Mode
ions app Write data to the end of the file
ios : : ate Shift to the end of the opened file
ios : : in Open the file for input
ios : : out Open the file for output
ios : : trunc If the file exists, then it will be cleaned
ios : : nocreate If the file does not exist, then a new file will not be created
ios : : noreplace If the file exists, then it will not be opened

The function open is used to link a stream to a file (to open the file for reading or writing). After the file is opened and linked to the stream, the work with the file is performed in the same way as with the standard input/output streams cin and cout.

When the end of the file EOF is reached, nothing can be read. To check a file state, we call the function eof ( ) , which returns true if the end of the file is reached, and false otherwise. The state of a file stream can be checked by using the stream identifier as a logical condition. After finishing the input/output operation, the file must be closed by the function close ( ) .

Listing 2.25.

If the contents of the file Test_in. dat is

then the result of the program execution is

2.6 Standard libraries

The standard library of C++ provides a collection of common classes and interfaces which expand significantly the core of C++.Some components of this library, which can be useful in a numerical solution of applied problems, are highlighted below. In most cases, the use of the C standard library is appropriate.

2.6.1 Work with time

The efficiency of a numerical algorithm is estimated, in particular, by time expenses. To work with time, the header file time. h of the C standard library or ctime of the C++ standard library should be included.

The function time (NULL) gets the current time time_t, with the value in seconds counted from January 1,1970. The function ctime returns time as a string: weekday, month, day, time (hour, minutes, seconds) and year.

The function clock returns time (the type clock_t) measured in processor cycles from the beginning of the program execution. The constant CLOCKS_PER_SEC determines the number of processor cycles per second.

Listing 2.26.

2.6.2 Common functions

We now need to discuss some useful utilities of the header file cstdlib of the C++ standard library (stdlib. h in C).

We have already met with some examples of common functions. For instance, we discussed above dynamic memory control using the library functions malloc, calloc, and free. Functions of search and sort can be of interest (bsearch and qsort).

We also note the possibility of transforming types. The functions atof and atoi are used to convert a string to a floating number and integer, respectively.

The following functions are intended to control the execution of a program: exit terminates the program, abort incorrect termination of the program, system executes an external command (command line).

Listing 2.27.

2.6.3 Work with strings

In C, strings are considered as arrays of symbols. As for C++, a special class of the standard library is used to easily work with strings. The class string is located in the namespace std. The header file string must be included in order to use the class.

Let us discuss some opportunities for working with strings using the class string. The overloaded operator + can be employed to concatenate (add) strings. The operator [ ] or the function at can be applied to select a symbol in a specified place of a string. The operations of assignment and comparison are supported by the operators =, ==, ! =. We can use the functions length (to get the length of a string), substr (to select a part of a string), find or rfind, copy, and replace. The function getline makes it possible to read a string from a specified stream.

Listing 2.28.

Output of the program execution: