How is the class related to data abstraction?


Basics of object-oriented programming in C ++


Next:Programming with C ++ Up:C ++ development with Linux Previous:Programming under Linux & nbsp Contents & nbsp index

Subsections

In this chapter I want to introduce you to the basics of object-oriented programming in C ++. We have an extensive workload ahead of us:

Since you only get to know the elementary terms of C ++ programming step by step, the examples are unfortunately mostly code snippets and not real programs. This is because language elements are always necessary that have not yet been discussed at the time. For this reason, this chapter demands a lot of perseverance from you, but guides you very briefly through all the depths of object-oriented programming with C ++. In the next chapter we will then apply the concepts we have learned in practice.

Learning object-oriented programming is difficult for two groups of people:

  1. Those who have never programmed;
  2. those who have already programmed.
I dare to say that the first group has it a little easier than the second. It has no well-established patterns of thought and action that it first has to overcome. However, the first steps in any programming are always difficult, so that there can be no question of a real advantage.

If you leaf through the job market for programmers and computer scientists, you will find that knowledge of object-oriented programming is in demand almost everywhere these days - regardless of whether it is C ++ or Java. In fact, more and more development projects are carried out according to this pattern (to put it more elegantly: paradigm). But success was a long time coming. The first object-oriented programming language existed as early as 1967. On the one hand, it was certainly the image as a language for scientific gimmicks that prevented widespread use. On the other hand, it was not until the breakthrough of graphical user interfaces such as Windows in the early 1990s that object orientation became popular. Because a window, a button or a menu are objects in a very natural way, which quickly showed that window applications are the easiest and fastest to program in an object-oriented manner. In addition, the increasing time and cost pressure at the software houses meant that aspects such as maintainability and reusability became more and more important. And the object-oriented approach promises more than any other to meet these demands.

Mastery of Complexity

If you've just started programming, most programs may seem simple and straightforward to you. Anyone who has a little more experience will agree with me that modern software systems are anything but simple. Today's information system is complex for a number of reasons, and unfortunately all too often to a very high degree. Often the problem is already very complex, because the user often wants to get a grip on all of his problems with software. Since such a system cannot be created by one person alone due to its size and the deadlines, there is also the difficulty of properly controlling the development process. In addition, a high degree of flexibility should always be guaranteed in order to be able to cope with tomorrow's requirements with today's investments. And finally, one must not forget that a computer is always only a discrete model of reality that permanently bears all the weaknesses associated with this modeling; This problem alone can lead to all sorts of unpleasant surprises, which one naturally wants to limit as much as possible.

Why am I telling you all this? You should get a first impression of the fact that problem solving with the help of software does not mean rushing to the computer immediately and starting with the first lines of code. Rather, it is becoming increasingly important to first give a lot of thought to the structure of the program (and the organization of the project). After all, you can only manage the complexity by dividing the system into smaller and smaller units (Figure 2.1).

The challenge for the developer now is to find the most suitable type of division. Because in the worst case, an inept division can really bring about chaos. The different programming paradigms also teach different types of division. So let's take a look at it first to understand how ultimately the object-oriented approach differs from its predecessors.

Review of structured programming

Despite my remark from earlier, I assume that you have already written programs, e.g. in Basic, Pascal, Java or C. Your very first programs will probably have been very unstructured, i.e. all instructions and all data in a main program. You are certainly not satisfied with that in the long run, be it that you wanted to enlarge the program and everything turned into even greater chaos, or be it that you put the program away, looked at it again after a while and could no longer understand it at all what you were actually thinking. Conclusion: Larger and professional programs need a structure to organize the chaos.

Procedures and modules

Procedural programming makes use of the simple fact that there are processes in almost every program that have to be processed several times in a similar form. These are then combined into a procedure that receives a set of parameters, uses them to complete a task and can then return a value. The program continues directly after the point at which the procedure was called.

The modular approach goes one step further and also combines procedures of related functionality into modules that represent coarser sub-units of the program. This can facilitate both the organization of the development project, since one programmer can be entrusted with a module at a time, as well as the testing, since the modules can already be tested separately and later only the correct interaction has to be examined. (Examples of modules are the units in Turbo / Borland Pascal or the modules in Fortran90. The programming language Modula-2, which was also designed as Pascal with modules, was also available quite early on.)

Each module should have a clearly defined interface feature. (This is understood to mean the entirety of all procedures that can be called from another module.) Then the overall system can also be divided into hierarchical layers of modules, with the modules of the upper layers offering more abstract and complex functionality that they can be called up by the modules below, which then contain the more specific instructions (the so-called lower level).

The data that the program handles is grasped Structures together, i.e. to groups with their own names that define a data type. Each module can have its own amount of data; If required, these are passed on in whole or in part to subordinate modules for processing.


Structured Programming Problems

This practice was common for many years. Over time, however, a number of problems emerged that kept cropping up and are therefore typical of this approach.

First of all, it is extremely difficult to ensure the robustness of the code itself. (This means aspects such as security against crashes, failure safety, ability to deal with unforeseen situations.) Memory for data structures must be reserved dynamically, that is, during the runtime of the program, in order to remain flexible. However, this memory must also be released again explicitly, i.e. by a program instruction; In addition, a program may not write in areas that it has not reserved. The problems that arise from this context alone are legendary and occur most seriously when using the C programming language.

In addition, the compiler is not able to check whether the data types match each other when passing parameters and assignments. Especially when exchanging incompatible information, there are always falsifications and serious rounding errors, for example missing signs.

Even more serious, however, are the problems that structured programming brings with it with regard to project organization.

  • If you make a change in a module on a lower level, this usually also requires changes to be made in the modules above.
  • If you want to use a module in another project (and this is often useful for reasons of content and costs), you have to take over all modules on which it depends.
  • Since the data structures are separate from the functions they process, changes to a data structure often require adjustments to functions and data flows.
So what's the bottom line? With a structured approach, maintenance is often very time-consuming and costly, and reusability is severely limited. This means that new projects with greater complexity are hardly possible. Of course, this summary does not necessarily apply to all software developed in this way. In practice, however, it has been shown that the problems described unfortunately occurred quite often.

However, you must not draw the reverse conclusion that with an object-oriented approach all difficulties are over. This is not a panacea either, because even an object-oriented project can go wrong. However, the concepts are very helpful in overcoming these (and other) problems. And that seems to be one of the main reasons for the popularity of object-oriented software development.


Objects

Most programs are written to model, support or automate processes in the real world. (And you write programs to have less trouble with other programs, but that's just a level of abstraction higher by one ...) In this world we are not surrounded by data structures, but by objects, i.e. animals, traffic lights, musical instruments or PCs (Figure 2.2). So if our programs are to relate to the physical world, it makes sense to deal with objects in the programs as well.

The first step in developing an object-oriented program is therefore always to look at the section of reality that is relevant for this program and to identify the objects and their relationships with one another. This phrase belongs to the class of advice that is so general that it is sure to be correct and plausible to everyone, but is incredibly difficult to heed in practice. It always depends on the problem and its context which objects a program should work with. A simple example is items that a store has in store for sale. These have a name and various other properties:

For another example, consider the simulation games that are very popular right now. Most of the time, the player has to found and build a settlement and think of the various influences that can get in his way. The whole scene usually consists of a multitude of different objects that more or less lead a life of their own. So if, for example, we are colonizing the planet Antares-3 want to program, we need a few spacecraft, among other things:

From both examples it becomes clear how an object is characterized: namely by its properties (also Attributes called). The kinds of properties are the same for each group of objects, but their values ​​are different. In real life, too, we distinguish objects based on their properties.

Another important characteristic is the behavior of an object. This depends on the Statusin which the object is currently located. A spacecraft should also stand, take off, fly and land in our simulation. These states merge into one another through commands from the commander (or our program). If the state of an object changes, its behavior often also changes.

There can also be different groups of states that mutually influence one another. For example, if the spacecraft is badly shot, it can no longer fly at all. The change from ready for use to shot down means that only certain movement states are possible.


Classes

Roughly speaking, our objects each have the same behavior. What they really differ in are the values ​​of their properties and states. So if we want to program a simulation, we don't have to implement all behavior patterns for each individual spacecraft (then our object-oriented approach would have caused us a lot of additional work!), But rather try to find a generally valid description for all spacecraft-type objects.

So let's combine the previously used attributes into a template: has the properties,,,, as well as. With this we have abstracted our knowledge of the elements. Such an abstraction is called one class. It is a general description of types of objects.

background

The essential characteristics of a class

So you already know the essential characteristics of a class:

  • A class corresponds to a template with which you can describe objects of the same type.
  • The class combines all properties and possible states of the objects that are relevant in this context.
  • An object is always an expression of a class. It is then also referred to as Instance or copy the class (for example: class, objects and).
  • Several objects of each class can exist at the same time.
  • Each class can contain variables, i.e. stored data. This is called Attributes or Data elements the class. You can have different values ​​for each object (example: origin, height). If you change the value of an attribute in an object, this change only applies to this object; all others remain unchanged.


Methods and process abstraction

If we were content with the properties and states of our objects alone, our programs would be pretty boring. This is because they would only give a very static view of the objects. But they say nothing about the behavior of the objects, i.e. about the dynamics. We also need functions and procedures for this.

We have seen Sec: Problem_structure that data and functions are separated in structured programming. Some of the problems we identified with this approach can be traced back to it. In object-oriented programming, on the other hand, data and functions form a unit. Because the behavior of the objects often depends directly on the values ​​of their attributes. The shuttle cannot fly faster than its top speed allows.

So how do we get an object to behave one way or another? We just tell him. Since we can't speak to him directly, we'll send him one message. That is exactly the way objects communicate with one another: They send messages to one another, which can then lead to changes in the status or an attribute.

The functions that belong to a class are called Methods (or Operations). They are used to send messages or to handle them. Methods mostly work within a specific instance of a class and access the attributes and states of this object. The changes made by the method are then only valid in this instance and have no influence on other instances that may still exist next to it at the moment.

Of particular importance is the principle of the so-called Process abstraction: For the sender of a message it is usually unimportant and therefore also unknown,

  • how the methods are implemented,
  • which data structures are required and processed,
  • what other objects are involved in processing the message.

Figure 2.4 shows some possible processes for communication between objects. First, the first object sends a message to the second. This cannot answer this request on its own and therefore asks a third object. This also returns an answer. The second object then changes its state. It can then compose the response to the original request and send it to the sender.

In actual programs, you will rarely find what looks like an actual news broadcast.Usually these are functions that you call on an object. In contrast to structured programming, however, in an object-oriented program you always have to specify the object to which the method you want to call belongs.


Data abstraction

The news point of view brings us to another aspect. If you can only modify an object by sending it a message, that means in practice that no direct access to the data, i.e. the properties and states, is possible from outside. It is said that the data is capsuled. Since the data is consequently not visible to the outside, i.e. outside of the respective object, other objects can neither read nor change it directly. You must always notify the owning object to do this (Figure 2.5). This can then determine for itself how it wants to react to such a message. It can grant the wish - or reject it. The object therefore retains full control over its data at all times.

Together with the principle of process abstraction, this also means that the sender of the message usually does not learn anything about the processing within the object. For example, you can change the processing algorithm or replace it entirely without the rest of the program noticing anything.

The abstraction of data and processes also has consequences for the organization of the development project. Usually each class is assigned to exactly one developer. He is then solely responsible for the internal processes in this class. All others only use the interface that it offers to the outside world and do not need to know how the class works internally. For example, if a bug occurs with an object of this class, the developer can usually fix it on his own. In structured programming, which does not know such levels of abstraction, the error correction usually affects several modules, data structures or functions at the same time, so that in many cases several developers have to be involved. The strict separation of responsibilities can - if practiced sensibly - make life considerably easier for everyone.

Summary

You should memorize the following points on this topic:

  • A class is a template that can be used to describe objects of the same type.
  • The class manages everyone properties and conditionsthat are important to their objects.
  • A object is an expression of a class. It is then also referred to as Instance one class. Several objects of each class can exist at the same time.
  • Each class can contain variables. This is called Attributes the class. Attributes can have different values ​​for each object. Changes only affect the changing instance.
  • Properties and states of an object can only be obtained through news to be changed. The actual data is generally not visible to other objects.
  • Methods are functions for handling and sending messages. They usually work within a specific instance of a class and access its properties and states.


Exercises

A popular example in the literature is the banking application.

  1. Design two classes and with a few properties that you think are relevant and define a few possible methods.
  2. Use the classes you have designed to explain the terms data abstraction and process abstraction. Which messages are exchanged between the objects?

So far we have talked a lot about the structure of programs and the organization of data and processes in objects, but not about programming. This is because writing good software requires even better preparatory work. This includes a very precise understanding of the problem that is to be solved, as well as a well thought-out design, i.e. a meaningful division of the data into classes and objects and a detailed definition of the messages that the objects are to exchange. Ultimately, it is now estimated that less than a third of the time and cost of a development project is spent on the actual programming.

But a good design also includes knowledge of the programming language in which the project will later be implemented. And besides, you didn't buy this book to learn software design, but to learn C ++ programming. Therefore, in this section we will become very specific and look at what C ++ is and why it can be used well for object-oriented programming.

Historical

It is not without reason that C ++ has the C in its name. It was originally designed (around 1980) to add the class concept to the C programming language widely used under Unix. That's why the developer, Bjarne Stroustrup, initially named his language C with Classes. Since it is a further development of C, the term C ++ was coined in 1983. In C, the operator means an increase of the adjacent variable by 1. (From this point of view, it is syntactically wrong to leave out the second plus ...)

Up until the early 1990s there were hardly any compilers for C ++, i.e. programs that turn the source code into a machine-readable and executable program. Usually a compiler was used, which then created C code from C ++ code, which could then be processed further with a normal C compiler. As you can imagine, this procedure posed some problems and could not be optimal. Today you only use your own C ++ compilers that generate machine code directly.

Since C ++ quickly found a large following, it became necessary to formally standardize the syntax, i.e. the rules for the language. Since 1991 a joint commission of the American standardization authority ANSI and the international ISO has been working on a standard for the C ++ language. During this time, the Commission published a number of drafts, all of which were taken up by the compiler manufacturers as de facto standards and taken into account in the development of their tools. (A detailed description of the history of development can be found in [pTROUSTRUP 1994].) In autumn 1998 a standard was actually passed that describes the language in great detail and to its maximum extent. But the work doesn't stop there either. There are already new drafts for extensions.

The basic language elements are of course supported by all current compilers. The individual tools only differ in how extensively and how well they cover the newer extensions. Fortunately, the GNU compiler used in this book, as of version 2.95, knows almost all language constructs of the ANSI / ISO standard. At the same time, however, writing a good program does not mean linking together all the latest features as possible. Especially if you have little experience with C ++, you should avoid the overly tricky constructs for your programs.

C ++ and C

Proximity to C is a key feature of C ++. Many of the problems that programmers have with C ++ can be traced back to this. The inheritance of C also means that the C ++ language does not seem to be all of a piece, but still supports many a construct for reasons of compatibility, which is actually not appropriate for a modern object-oriented programming language. This leads to the situation that the language allows for a variety of programming styles, from purely procedural to strictly object-oriented. So some people write programs in C ++ that they think are object-oriented, but that are only modular.

What remains to be said is that C ++ is a superset of C (Figure 2.6), that is, it has all the syntax properties of C, but a few more. The advantage is that existing C code can be integrated into any C ++ program without any problems - if you want to and think it makes sense.

C ++ and Linux

Unix and the C programming language are very closely related. C was designed for Unix, and almost all Unix implementations were written in C. The Linux kernel is also written in C.

Over time, however, the developers under Unix have also recognized the advantages of the object-oriented approach. It may not be so obvious in low-level programs, so that C still prevails here today. In the case of application programs, in particular those with a graphical user interface, on the other hand, the gain in conception, programming based on the division of labor and maintenance / improvement is clearly noticeable. A number of very good C ++ libraries (for example wxWindows, V or Qt) are available today for the development of user interfaces. For example, the entire KDE work environment (see www.kde.org) and the applications written for it are based on the Qt library. So you see, if you go for C ++ on Linux, you are not completely wrong.

For a long time, the standard compiler under Linux was the GCC, i.e. the GNU C compiler, which was developed as free software in a tried and tested manner. Although it also includes a C ++ compiler (called g ++) was expanded, the developers could not keep up with the speed at which the C ++ language was evolving. In 1997, a small group set about going one step further on the basis of the GCC and supporting additional features. The project was called experimental GNU compiler suite, for short egcs, spoken eggs. In April 1999, those responsible put an end to the parallelism of developments and declared the egcs to be the official GNU compiler. Since version 2.95 from summer 1999 there is again only one GCC, which is now to be called the GNU compiler collection; since no one has got used to the new name and the associated new gender in German, I will continue to use the GCC speak.

We will work with this in the following. It supports almost all language features of the current standard. In any case, we will not discuss the few aspects that are not yet fully supported in this context.

The exact handling of this compiler is given in section on page explained.

But the GCC isn't the only C ++ compiler available on Linux. Commercially available, for example, are the compilers from the Portland Group (to be found at www.pgroup.com), from Kuck & Associates (see www.kai.com/C_plus_plus) or from Metrowerks (www.metrowerks.com, see also page ). Borland / Inprise also offers a command line version of their C ++ compiler for free download for Linux (available at www.borland.com).

The first C ++ program

If you've read the book this far, you will probably be waiting impatiently to see when the right programming will finally start. So now the first program.

In programming textbooks, it has become common practice to start every introduction to a new language with a program that does nothing except the words Hello World! to spend. You will certainly not hold it against me if I save ourselves this step and take a look at the following program with me:

Do you already have any idea what purpose it might have? First of all, of course, it should show you a few lexical elements of the C ++ language. We'll get to the issue later ...

The program is so simple that it only takes one file with that piece of code. On a header file, as on page we can do without it.

By the way, you will find all of the example programs presented in this book on the enclosed CD-ROM in the subdirectory of the respective chapter. But that shouldn't prevent you from typing in one or the other example yourself. Because most of the time you make a typo and learn how the compiler reacts to such errors.

Comments

The first three lines are a comment. This is understood as a text, a comment that is ignored by the compiler. It only serves to make the program text easier to understand for a human reader. With such a small program, this may not seem particularly important to you. For larger programs, however, good commentary is often crucial. For example, if you put your program aside for a few months and then want to know exactly what it's doing, good comments are a great help. The same is true if you want to understand programs that others have written.

Many programmers find commenting a chore - and that's exactly what their comments look like. I can only advise you to comment as much as possible, including things that you take for granted at the moment; maybe others don't see it that way. As a rule of thumb, one can say: A well-commented program has at least as many program lines as there are comment lines.

There are two ways to declare comments in C ++:

  1. With two slashes, all characters up to the end of the line belong to the comment. The next line then continues with the program code. This option is more suitable for single-line comments and comments after commands.
  2. With a slash and asterisk, all characters from to are part of the comment, regardless of whether they are on one line or on several lines. In this way you can include longer comments in the source code.
Another useful use of comments is to comment out how to say individual instructions. For example, if you want to test what your program does without a specific instruction, just put the two slashes in front of it and the compiler will ignore this instruction.


variables

In almost every program you have to deal with some kind of data. To do this, you need memory locations in the computer in which you can save this data. Such a memory location is called a Variable, precisely because it can change its value (that is, its content) in the course of the program. In C ++ one differentiates between the variables according to their type, i.e. whether they can hold numbers or words or something else. Numbers are very important types; There are several types for whole numbers and for decimal fractions - depending on the range of numbers that can be represented with them. But more on that later (on page ).

Each variable has a name. In our example there are two variables, namely and. Before you can use a variable, you must first declare it. That is, you write something like (as in line 10)


indicating that you are using a variable with the name of type (like Integer, i.e. integer) in the following program. With this instruction, the compiler reserves the necessary memory space and notices that the variable with this name is linked to this memory space. You can also declare several variables of the same type together by placing them next to each other, separated by commas. It is also allowed to assign a value to the variable when it is declared, i.e. to initialize it.

You are pretty free when it comes to naming variables, although you have to follow a few rules: The name must begin with a letter or an underscore () and then consist of uppercase and lowercase letters, as well as digits and underscores. Spaces and special characters are not allowed. The maximum length is 250 characters, but more than fifteen to twenty characters is pretty impractical. Also, keep in mind that C ++ is case-sensitive; So you have to use all names exactly as you declared them.

C ++ inherited a bad habit from C: Variables are not initialized when they are declared. This means that they have no defined value after the declaration, but can have all possible values. This is particularly important if you continue working with this variable and increase it, for example, as in line 16. A number is added to the current value. If the current value is already undefined (which it is not in this example thanks to the initialization in line 11), the result is the same. You should therefore initialize each variable with a meaningful value immediately after it has been declared in order to prevent such unpleasant effects. However, if you are lucky, the compiler is already intelligent enough to pre-allocate the values ​​of the variables. In this case, the GCC sets the variable to 0. However, you should not expect such good behavior everywhere.

Operators

An assignment to a variable is done simply with the operator, as you can see in line 11. Of course, you can also assign the value of another to one variable or a calculation result, as in line 16. There, a single operator is used for calculation and assignment, the. This command means the same as


There are a few more of this type of operator in C ++; therefore I will come back to it in a moment (Sec: Operators).

A special type of operator is used for input and output. In the example above, on line 17 you could read something like:


The operator means nothing more than that everything that is to the right of it is passed on to the left.This handover ends on the one that represents the output on the screen (for example in the shell window). With this line we output two texts with a number in the middle.

Structuring elements

And you can see something else in this example: Every statement in C ++ ends with a semicolon. Control structures such as the loop are an exception. This is followed by either a single instruction or one block. Such blocks are marked in C ++ with curly brackets and. For example, each function consists of a block. Of course, you can also nest several blocks one inside the other.

In order to maintain an overview, I recommend that you put each curly bracket on its own line. This is another characteristic of C ++: almost all blank lines and line breaks are ignored by the compiler. So whether you insert one or ten spaces between the type and the variable name in a variable declaration, for example, does not matter at all. You should use the freedom you consequently have when designing the source text to write the program text as readable as possible (for you and others!). A few basic rules are:

  • only one statement per line
  • indent all statements evenly within a block (e.g. by two spaces per block)
  • Group instructions by inserting blank lines
But since the design of the program text is ultimately a matter of taste, opinions naturally diverge as to what the best way of writing is. In a later section (from page ) I'll suggest a few more conventions for you to write your programs can. How you actually do it, however, is up to you. The main thing is that you (and possibly your team) write everything according to uniform rules. Then an important step has generally already been taken to ensure that the program remains readable and thus maintainable.


Preprocessor instructions

Another typical quirk of C compilation is the use of a preprocessor. Most of the time you don't even notice his work. Before the actual compiler run, however, preprocessing is still done. The preprocessor prepares the code for the compiler by adding the specified header files or expanding macros. (Macros are something like the abbreviation of a few instructions.) It can even be controlled via conditions, so that the compiler then only translates certain parts of the source code.

You can always recognize instructions for the preprocessor by the double cross symbol. To get started, all you need to know is the command (used on line 5). This indicates that you want to use the header file whose name you put in angle brackets (and) or in quotation marks after it. The difference is: If the file name is in normal quotation marks, the header file is also searched for in the current directory. If you use the angle brackets, the search is limited to the directories for the system headers and specially specified directories (via the call parameters for the compiler, see page ).

The main function

Every program has to start somewhere. In C ++ this beginning is always in a function called. Even if there are completely different functions in front of it, the execution always starts in this function. As a result, the compiler expects every executable program to have a function by that name.


Data types and type conversion

By defining the data type, you determine how the compiler interprets the information and how it stores it in memory. The type of operations that are permitted with this variable also depend on its data type. As above (page ), the definition is made when the variables are declared, for example:

Variable declared as an integer
Three variables as simple characters
Floating point number initialized the same


On the one hand, C ++ has a number of built-in types (so-called standard or elementary data types), but on the other hand it also offers the option of defining your own data types based on them, including classes.

The elementary data types

These are differentiated according to their use:

  • Logical (Boolean) variables: These can only assume the values ​​or.


    (Note: This data type comes from a newer version of the C ++ standard and is not yet supported by all compilers. However, the current GCC handles it without any problems.)
  • character (character): Small whole numbers (in the range of one byte) or characters

    1 byte (-128 to 127)

    Letters correspond to their code in the ANSI character set; this is e.g. the value 65.

  • Integers (integrity) are available in several sizes, i.e. value ranges
    2 bytes (-32,768 to 32,767)
    4 bytes (from -2,147,483,648 to 2,147,483,647)
    4 or 8 bytes (depending on the platform!)

    Thereby and are only abbreviated spellings for or.

  • Floating point numbers can be stored with single or double precision
    4 bytes (1.2E-38f to 3.4E38f)
    8 bytes (2.2E-308 to 1.8E308)

    (Caution: Although it is in German Gleitcommanumber means, you have to enter all numbers in C ++ according to the Anglo-Saxon convention, i.e. with a decimal point.)

  • In addition,,, and can be given the addition (the addition to enlarge the range of values), for example


    The default is always; therefore, for an unsigned integer, you can just write:


  • Plus there is still. This actually means a non-existent value. It is mainly used to indicate that a subroutine does not need any transfer parameters or does not return any values.

From the examples you can also see how to use literal Constants specifies (i.e. those whose value is directly in the program text). Remember the following rules:

  1. Whole numbers (i.e. without a decimal point after them) are interpreted as. If you want to specify a long integer, you have to put that after it.
  2. Likewise, every floating point number, i.e. those that contain a decimal point, is automatically regarded as. If you just want to express the simple precision, there needs to be one behind it.
  3. If you want, you can also specify whole numbers in hexadecimal format. To do this, you have to precede the value, for example.
  4. The single apostrophe is used for individual characters, e.g.. This constant can then be assigned to a variable of the type.


Implicit cast

Usually you can assign variables and constants of different data types to one another. C ++ is able to do the necessary conversions automatically. As a programmer, however, you should know a little about the principles involved in order to be able to judge whether the automatic conversion is what you want.

The conversion from a data type with a smaller to one with a larger range of values, for example from to, is completely unproblematic. Caution is advised in the reverse case. Information can be lost and the results may be completely different from what you might expect. An example:


What output do you expect? The correct result would be 49284, but -16252 appears on the screen. This is because the number of bits in the variable is insufficient to store that number. The result is generated correctly and written to the memory location; but the front bits are missing. In addition, the highest bit of integers (unless they are declared as) is always regarded as a sign. So if you add 1 to the highest value 32767, your variable will then contain the value -32768.

If there are still constants in the source code, you can do the calculations by hand and pay attention. But when other variables are involved, it becomes more difficult, for example:


You should therefore always make sure that you do not risk any loss of information during assignments (or transfers to subroutines and so on) and thus any undesired type conversion.

There are not so many pitfalls in the mutual assignment of whole and decimal numbers. Just keep in mind that if you enter an integer as the result, the entire part will be separated after the comma. For example, delivers


as a result 1.

C ++ compilers have a certain degree of flexibility when it comes to implicit type conversion, but they are usually much more precise than C compilers. That's because C ++ has a strictly typed language is as they say. Each variable must have a unique type, and in the case of assignments and comparisons, the variables or constants must be known as compatible, otherwise an error message is output. In general, the compiler often uses warnings to point out possible errors or ambiguities, for example if it assumes that you meant a statement differently from what it is now in the source code. Read these messages carefully and always try to understand the causes. That way, you will learn a lot about programming properly too.


Explicit cast

Instead of relying on automatic type conversion, it can sometimes be useful to tell the compiler a rule to use for conversion. In this way you can prevent misunderstandings that would otherwise come to light in the form of warnings.

For the explicit type conversion, the C programmers use a very figurative expression, namely cast, the English word for plaster cast. You have various options in C ++ to create such a variable. The C variant is to write the type in round brackets in front of the variable, namely where the converted value should be in its place, for example


When converting from to, all decimal places are cut off; there is no rounding.

The other possibility is to put the variable in brackets and the type in front of it:


(If you want to be absolutely sure, you can even use both variants at the same time ...)

There are a few more sophisticated methods for explicit type conversion in the new C ++ standard. However, since you first have to know a few more terms in order to understand them, we postpone the discussion until later (page ).


Enumeration types

Numerical values ​​are not always useful for a variable. Sometimes you only want to allow a limited range of values ​​for them. This can be, for example, the distinction between working day, Sunday and public holiday, but also an error status such as success, information, warning, error and cancellation. Of course, you can represent these values ​​by an integer data type in the program, for example


where the case of success, the information, the warning, the error and the termination represent. In this case, however, you cannot immediately recognize which type of status is meant when assigning or comparing. It would also be permissible for you to assign the variable, for example, the value that is outside the value range 0 to 4 and can no longer be meaningfully interpreted.

Here you should get one Enumeration type use. You declare it with the keyword, a type name, and a list of values, enclosed in curly braces and separated by commas. For our status we can write:


(You can spell the values ​​in any way you like, but I recommend that you use the convention of writing constants with capital letters to make them easier to distinguish from variables.)

You can now define variables


and, if necessary, initialize it at the same time:


It is also permissible to define variables of it when declaring an enumeration type, for example:


If you only need the enumeration type for a variable definition and not otherwise, you can even omit the type name and declare it anonymously, for example:


Although you are declaring new data types, enumerated types are managed internally as natural numbers. The first constant always receives the value, the next one increased by. As a result, you can also convert values ​​of an enumeration type to, but not vice versa.


Operators

Variables alone are not of much use. You also have to be able to link them together, assign them, change them and output them. The operators are used for this. Almost all special characters that the keyboard provides have a meaning as operators in C ++. In addition to the simple math like and there are also very unusual ones that many programmers never come into contact with. Some still remember that C was once designed as a particularly low-level language.

overview

Going into each one individually would lead too far at this point. I therefore want you in table Tab: Operators give a list of the most important operators. If you don't understand some of them straight away, don't worry: if you have some experience in C ++ programming, you will understand all operators; I will go into some of them in more detail below.


Operators are used for so many purposes that even the characters on the keyboard sometimes seem to be insufficient. In fact, there are a few operators, the meaning of which depends on the context in which they are used. The ampersand has the largest range. It serves as a referencing operator if there is no argument in front of it - otherwise it is a bitwise AND operation. You also make a reference declaration out of a variable declaration. Over time, you will most likely become significantly more confident in reading C ++ programs, so these differences will eventually become obvious to you. For the moment it is helpful if you look through the source texts very carefully and ask yourself what the meaning of each instruction is.


priorities

Even with the basic arithmetic operations, it can make a significant difference which calculation is carried out first for larger terms. There, for example, the principle of point before line regulates that it is first multiplied and only then added. Every programming language also needs such a sequence of processing the operators, otherwise an endless number of brackets would have to be set, which would make the program text extremely confusing.

In table the operators are already sorted according to their priorities, that is, the primary operators are evaluated first, then the unary, then the binary and at the end the assignment operators. There can also be orders within each group. As expected, the multiplication has priority over the addition, but also the subtraction over the comparison.


The increment operator

The operators for incrementation and decrementation occupy a special position. They can be in front of or behind the variable they affect. These two positions are also called prefix and Postfix.

The operators are usually not used as the only part of an instruction, but rather built into more complex expressions. The rule is: If the operator stands in front the variable, he will run first and only then the expression is evaluated. Does he oppose it? behind, becomes only the entire expression is evaluated and then the operator applied. For example:


Here the current value of is still used for calculation and it is only increased by 1 after the assignment.

Beginners always find this spelling confusing; the experienced programmers, on the other hand, see them as particularly elegant and compact. Think about (or try) for yourself which output the following code generates:


You should absolutely avoid adding multiple increment operators to a variable that occurs more than once in an expression. The result can then quickly become unpredictable. (In order not to give a misleading example, I'll save the example for this case. The code in the last section is bad enough!)


The conditional operator

One of the operators in table absent is for the condition. It has the following general form:

The use is very simple: if the condition is true, then becomes Expression1 evaluated, if it is wrong, then Expression2. For example:


If the value of the variable is other than 5, it is given the value 25, otherwise it is set to 50.

Expressions

We have just spoken of expressions. What is an expression anyway? The concept of Expression (engl.expression) corresponds roughly to that of the term in mathematics, i.e. a combination of constants, variables and operators. An expression is evaluated in the program, that is, the links and modifications determined by the operators are calculated; the result of this evaluation is then called the value of the expression.

In C ++, this value always has a well-defined type. This depends on the variables and operators involved. Simple examples are:

ExpressionType
if is of the type


An expression often consists of several nested sub-expressions that are linked with operators, for example


The priorities according to which an expression is evaluated are based on those of the operators involved (see page ). This is about


first calculated and then added the result to.

The type that the value of an arithmetic expression receives is determined by the most significant partial expression, i.e. by the type with the largest amount of information. For example, consider the following variables:


Then the values ​​of the links of these variables are given the following types:


You can prevent this automatic type definition by explicit type conversion (see page ). This can be useful if the result would otherwise be falsified by rounding, for example


Summary

Here are some things to keep in mind from this section:

  • C ++ is a superset of C, so it has all the language elements of C in addition to its own. Under Unix, C and C ++ are the most frequently used programming languages.
  • Comments can be inserted into the program text in two ways: With you comment out everything up to the end of the line, with everything up to the end. Every program should contain at least as many comment lines as instruction lines.
  • When declaring a variables first enter the type and then the name. There is no automatic initialization.
  • Use the preprocessor command to include header files with declarations of library functions and data structures from other source code files.
  • As Types for integers there are, and, depending on the range of values. Floating point numbers can be specified with single (as) or double precision (). The types,, and can have the addition. The data type stands for a non-existent value.
  • If the data types within an expression are not compatible with one another, the compiler tries to convert the variables to another type on its own. You can also explicitly influence this process Type conversions prescribe. The type of the value of an arithmetic expression is determined by the most significant subexpression.
  • Data and objects are created with the help of Operators linked, changed and read out. These have graduated priorities among each other; Brackets can override this.

Exercises

  1. What happens if you assign a number with decimal places to a variable of the type?
  2. What is the value of a variable after it has been declared?
  3. Explain the difference between explicit and implicit type conversions.
  4. The purpose of the function is to determine the memory consumption of a data type or a variable. Which output does the following program deliver?


    Enter the program and save it to the file typesize.cc. Then enter in the shell:


    If you made no mistake, this is the executable typesize new in your directory. Start these and compare their expenses with your predictions.
  5. For a variable it should be output whether it is 0 or not. What is wrong here?


The C ++ compiler of the GNU Project (GCC) is very popular because of its widespread use, its availability on many platforms, and its efficiency. Of course, the fact that this is free software also plays a role, i.e. the compiler is available free of charge. On Linux he is the Standard compiler for C and C ++ programs.

installation

You can always get the latest version of the compiler from the Internet, preferably from gcc.gnu.org.

However, you will hardly ever feel the need to do so. This compiler is included in every Linux distribution - if only because it is needed to compile the Linux kernel. When a new version is released, the manufacturers of the distributions usually put it relatively quickly in the form of installation packages that you then only need to download from the manufacturers' sites. The actual installation on your computer is then with the respective graphic tools or with rpm easy to do.

(If you do want to translate the GCC yourself, you will find it in the file enclosed with the sources INSTALL all necessary information and instructions.)

Call and options

The executable file of the C ++ compiler has the name g ++. In the simplest form of the call, the name of the source text file must be given as the only argument, for example


If there are no errors, the compiler will not display any text on the screen. After a short time, only the command prompt of the shell responds. In the current directory there is then a new executable file called a.out. (This has been the standard name for all programs since the old days of C.)

If your program consists of several source code files, you can also specify several in a row. The files can be in several directories, you only have to enter the full path, for example:


The GNU compiler knows a wealth of options with which the translation process can also be influenced.