50
1. Структура программы main, params, #define // my second program in C++ #include <iostream> using namespace std; int main () { cout << "Hello World! "; cout << "I'm a C++ program"; } Line 2: #include <iostream> Lines beginning with a hash sign (#) are directives read and interpreted by what is known as the preprocessor. They are special lines interpreted before the compilation of the program itself begins. In this case, the directive#include <iostream>, instructs the preprocessor to include a section of standard C++ code, known as header iostream, that allows to perform standard input and output operations, such as writing the output of this program (Hello World) to the screen. Line 4: int main () This line initiates the declaration of a function. Essentially, a function is a group of code statements which are given a name: in this case, this gives the name "main" to the group of code statements that follow. Functions will be discussed in detail in a later chapter, but essentially, their definition is introduced with a succession of a type (int), a name (main) and a pair of parentheses (()), optionally including parameters. The function named main is a special function in all C++ programs; it is the function called when the program is run. The execution of all C++ programs begins with the main function, regardless of where the function is actually located within the code. Line 6: std::cout << "Hello World!"; This line is a C++ statement. A statement is an expression that can actually produce some effect. It is the meat of a program, specifying its actual behavior. Statements are executed in the same order that they appear within a function's body. This statement has three parts: First, std::cout, which identifies the standard character output device (usually, this is the computer screen). Second, the insertion operator (<<), which indicates that what follows is inserted intostd::cout. Finally, a sentence within quotes ("Hello world!"), is the content inserted into the standard output. Notice that the statement ends with a semicolon (;). This character marks the end of the statement, just as the period ends a sentence in English. All C++ statements must end with a semicolon character. One of the most common syntax errors in C++ is forgetting to end a statement with a semicolon. If you have seen C++ code before, you may have seen cout being used instead of std::cout. Both name the same object: the first one uses its unqualified name (cout), while the second qualifies it directly within the namespace std (asstd::cout). cout is part of the standard library, and all the elements in the standard C++ library are declared within what is a called anamespace: the namespace std. In order to refer to the elements in the std namespace a program shall either qualify each and every use of elements of the library (as we have done by prefixing cout with std::), or introduce visibility of its components. The most typical way to introduce visibility of these components is by means of using declarations: using namespace std; The above declaration allows all elements in the std namespace to be accessed in an unqualified manner (without thestd:: prefix). -----------------------------------------------------------------------------------------------------

C++ resumen.pdf

Embed Size (px)

Citation preview

Page 1: C++ resumen.pdf

1. Структура программы main, params, #define

// my second program in C++

#include <iostream>

using namespace std;

int main ()

{

cout << "Hello World! ";

cout << "I'm a C++ program";

}

Line 2: #include <iostream>

Lines beginning with a hash sign (#) are directives read and interpreted by what is known

as the preprocessor. They are special lines interpreted before the compilation of the

program itself begins. In this case, the directive#include <iostream>, instructs the

preprocessor to include a section of standard C++ code, known as header iostream, that allows to perform standard input and output operations, such as writing the output of this

program (Hello World) to the screen.

Line 4: int main ()

This line initiates the declaration of a function. Essentially, a function is a group of code statements which are given a name: in this case, this gives the name "main" to the group of code statements that follow. Functions will be discussed in detail in a later chapter, but essentially, their definition is introduced with a succession of a type (int), a name (main)

and a pair of parentheses (()), optionally including parameters.

The function named main is a special function in all C++ programs; it is the function called

when the program is run. The execution of all C++ programs begins with the main function, regardless of where the function is actually located within the code.

Line 6: std::cout << "Hello World!";

This line is a C++ statement. A statement is an expression that can actually produce some effect. It is the meat of a program, specifying its actual behavior. Statements are executed in the same order that they appear within a function's body.

This statement has three parts: First, std::cout, which identifies

the standard character output device (usually, this is the computer screen). Second, the

insertion operator (<<), which indicates that what follows is inserted intostd::cout.

Finally, a sentence within quotes ("Hello world!"), is the content inserted into the standard output.

Notice that the statement ends with a semicolon (;). This character marks the end of the

statement, just as the period ends a sentence in English. All C++ statements must end with a semicolon character. One of the most common syntax errors in C++ is forgetting to end a statement with a semicolon.

If you have seen C++ code before, you may have seen cout being used instead of std::cout.

Both name the same object: the first one uses its unqualified name (cout), while the second

qualifies it directly within the namespace std (asstd::cout).

cout is part of the standard library, and all the elements in the standard C++ library are declared

within what is a called anamespace: the namespace std.

In order to refer to the elements in the std namespace a program shall either qualify each and

every use of elements of the library (as we have done by prefixing cout with std::), or introduce

visibility of its components. The most typical way to introduce visibility of these components is by means of using declarations:

using namespace std;

The above declaration allows all elements in the std namespace to be accessed in

an unqualified manner (without thestd:: prefix).

-----------------------------------------------------------------------------------------------------

Page 2: C++ resumen.pdf

Help you to input Params dynamic input parameters …

By using the params keyword, you can specify a method parameter that takes a variable number of

arguments.

You can send a comma-separated list of arguments of the type specified in the parameter declaration

or an array of arguments of the specified type. You also can send no arguments. If you send no

arguments, the length of the params list is zero.

No additional parameters are permitted after the params keyword in a method declaration, and only

one params keyword is permitted in a method declaration.

public class MyClass

{

public static void UseParams(params int[] list)

{

for (int i = 0; i < list.Length; i++)

{

Console.Write(list[i] + " ");

}

Console.WriteLine();

}

public static void UseParams2(params object[] list)

{

for (int i = 0; i < list.Length; i++)

{

Console.Write(list[i] + " ");

}

Console.WriteLine();

}

static void Main()

{

// You can send a comma-separated list of arguments of the

// specified type.

UseParams(1, 2, 3, 4);

UseParams2(1, 'a', "test");

// A params parameter accepts zero or more arguments.

// The following calling statement displays only a blank line.

UseParams2();

// An array argument can be passed, as long as the array

// type matches the parameter type of the method being called.

int[] myIntArray = { 5, 6, 7, 8, 9 };

UseParams(myIntArray);

object[] myObjArray = { 2, 'b', "test", "again" };

UseParams2(myObjArray);

// The following call causes a compiler error because the object

// array cannot be converted into an integer array.

//UseParams(myObjArray);

// The following call does not cause an error, but the entire

// integer array becomes the first element of the params array.

UseParams2(myIntArray);

}

Page 3: C++ resumen.pdf

}

/*

Output:

1 2 3 4

1 a test

5 6 7 8 9

2 b test again

System.Int32[]

*/

----------------------------------------------------------------------------------------------------------------------------- --------------------------------------

The preprocessors are the directives, which give instruction to the compiler to preprocess the information before actual compilation starts.

All preprocessor directives begin with #, and only white-space characters may appear before a preprocessor directive on a line. Preprocessor directives are not C++ statements, so they do not end in a semicolon (;).

You already have seen a #include directive in all the examples. This macro is used to include a header file into the source file.

There are number of preprocessor directives supported by C++ like #include, #define, #if, #else, #line, etc. Let us see important directives:

The #define Preprocessor: The #define preprocessor directive creates symbolic constants. The symbolic constant is called amacro and the general form of the directive is:

#define macro-name replacement-text

When this line appears in a file, all subsequent occurrences of macro in that file will be replaced by replacement-text before the program is compiled. For example:

#include <iostream>

using namespace std;

#define PI 3.14159

int main ()

{

cout << "Value of PI :" << PI << endl;

return 0;

}

Now, let us do the preprocessing of this code to see the result, assume we have source code file, so let us compile it with -E option and redirect the result to test.p. Now, if you will check test.p, it will have lots of information and at the bottom, you will fine the value replaced as follows:

$gcc -E test.cpp > test.p

...

int main ()

{

cout << "Value of PI :" << 3.14159 << endl;

return 0;

}

Function-Like Macros: You can use #define to define a macro which will take argument as follows:

#include <iostream>

using namespace std;

Page 4: C++ resumen.pdf

#define MIN(a,b) (((a)<(b)) ? a : b)

int main ()

{

int i, j;

i = 100;

j = 30;

cout <<"The minimum is " << MIN(i, j) << endl;

return 0;

}

If we compile and run above code, this would produce the following result:

The minimum is 30

Conditional Compilation: There are several directives, which can use to compile selectively portions of your program's source code. This process is called conditional compilation.

The conditional preprocessor construct is much like the if selection structure. Consider the following preprocessor code:

#ifndef NULL

#define NULL 0

#endif

You can compile a program for debugging purpose and can debugging turn on or off using a single macro as follows:

#ifdef DEBUG

cerr <<"Variable x = " << x << endl;

#endif

causes the cerr statement to be compiled in the program if the symbolic constant DEBUG has been defined before directive #ifdef DEBUG. You can use #if 0 statment to comment out a portion of the program as follows:

#if 0

code prevented from compiling

#endif

Let us try the following example:

#include <iostream>

using namespace std;

#define DEBUG

#define MIN(a,b) (((a)<(b)) ? a : b)

int main ()

{

int i, j;

i = 100;

j = 30;

#ifdef DEBUG

cerr <<"Trace: Inside main function" << endl;

#endif

#if 0

/* This is commented part */

cout << MKSTR(HELLO C++) << endl;

#endif

cout <<"The minimum is " << MIN(i, j) << endl;

#ifdef DEBUG

cerr <<"Trace: Coming out of main function" << endl;

#endif

return 0;

Page 5: C++ resumen.pdf

}

If we compile and run above code, this would produce the following result:

Trace: Inside main function

The minimum is 30

Trace: Coming out of main function

The # and ## Operators: The # and ## preprocessor operators are available in C++ and ANSI/ISO C. The # operator causes a replacement-text token to be converted to a string surrounded by quotes.

Consider the following macro definition:

#include <iostream>

using namespace std;

#define MKSTR( x ) #x

int main ()

{

cout << MKSTR(HELLO C++) << endl;

return 0;

}

If we compile and run above code, this would produce the following result:

HELLO C++

Let us see how it worked. It is simple to understand that the C++ preprocessor turns the line:

cout << MKSTR(HELLO C++) << endl;

into the following line:

cout << "HELLO C++" << endl;

The ## operator is used to concatenate two tokens. Here is an example:

#define CONCAT( x, y ) x ## y

When CONCAT appears in the program, its arguments are concatenated and used to replace the macro. For example, CONCAT(HELLO, C++) is replaced by "HELLO C++" in the program as follows.

#include <iostream>

using namespace std;

#define concat(a, b) a ## b

int main()

{

int xy = 100;

cout << concat(x, y);

return 0;

}

If we compile and run above code, this would produce the following result:

100

Let us see how it worked. It is simple to understand that the C++ preprocessor transforms:

cout << concat(x, y);

Page 6: C++ resumen.pdf

into the following line:

cout << xy;

----------------------------------------------------------------------------------------------------------------------------- --------------------------------------

Include guard From Wikipedia, the free encyclopedia

The correct title of this article is #include guard. The substitution or omission of the # is because of technical restrictions.

It has been suggested that pragma once be merged into this article.

(Discuss) Proposed since March 2013.

In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive. The addition of #include guards to a header file is one way to make that file idempotent.

Contents

[hide]

1 Double inclusion

2 Use of #include guards

3 Difficulties

4 See also

5 External links

6 References

Double inclusion[edit]

The following C code demonstrates a real problem that can arise if #include guards are missing:

File "grandfather.h"

struct foo {

int member;

};

File "father.h"

#include "grandfather.h"

File "child.c"

#include "grandfather.h"

#include "father.h"

Here, the file "child.c" has indirectly included two copies of the text in the header

file "grandfather.h". This causes a compilation error, since the structure type foo is apparently

defined twice. In C++, this would be a violation of the One Definition Rule.

Use of #include guards[edit] File "grandfather.h"

#ifndef GRANDFATHER_H

#define GRANDFATHER_H

struct foo {

int member;

};

Page 7: C++ resumen.pdf

#endif /* GRANDFATHER_H */

File "father.h"

#include "grandfather.h"

File "child.c"

#include "grandfather.h"

#include "father.h"

Here, the first inclusion of "grandfather.h" causes the macro GRANDFATHER_H to be defined.

Then, when "child.c" includes "grandfather.h" the second time, the #ifndef test returns false,

and the preprocessor skips down to the #endif , thus avoiding the second definition of struct

foo . The program compiles correctly.

Different naming conventions for the guard macro may be used by different programmers. Other common forms of the above example

includeGRANDFATHER_INCLUDED , CREATORSNAME_YYYYMMDD_HHMMSS (with the appropriate

time information substituted), and names generated from a UUID. (However, names starting with

one or two underscores, such as _GRANDFATHER_H and __GRANDFATHER_H , are reserved to

the implementation and must not be used by the user.[1][2]) It is important to avoid duplicating the name in different header files, as including one will prevent the symbols in the other being defined.

Difficulties[edit]

In order for #include guards to work properly, each guard must test and conditionally set a different preprocessor macro. Therefore, a project using #include guards must work out a coherent naming scheme for its include guards, and make sure its scheme doesn't conflict with that of any third-party headers it uses, or with the names of any globally visible macros.

For this reason, most C and C++ implementations provide a non-standard #pragma

once directive. This directive, inserted at the top of a header file, will ensure that the file is

included only once. The Objective-C language (which is a superset of C) introduced

an #import directive, which works exactly like#include , except that it includes each file only

once, thus obviating the need for #include guards.[3]

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2. Типы данных

Data Types

While doing programming in any programming language, you need to use various variables to store various information. Variables are nothing but reserved memory locations to store values. This means that when you create a variable you reserve some space in memory.

You may like to store information of various data types like character, wide character, integer, floating point, double floating point, boolean etc. Based on the data type of a variable, the operating system allocates memory and decides what can be stored in the reserved memory.

Primitive Built-in Types: C++ offer the programmer a rich assortment of built-in as well as user defined data types. Following table lists down seven basic C++ data types:

Type Keyword

Boolean bool

Character char

Page 8: C++ resumen.pdf

Integer int

Floating point float

Double floating point double

Valueless void

Wide character wchar_t

Several of the basic types can be modified using one or more of these type modifiers:

signed

unsigned

short

long

The following table shows the variable type, how much memory it takes to store the value in memory, and what is maximum and minimum vaue which can be stored in such type of variables.

Type Typical Bit Width Typical Range

char 1byte -127 to 127 or 0 to 255

unsigned char 1byte 0 to 255

signed char 1byte -127 to 127

int 4bytes -2147483648 to 2147483647

unsigned int 4bytes 0 to 4294967295

signed int 4bytes -2147483648 to 2147483647

short int 2bytes -32768 to 32767

unsigned short int Range 0 to 65,535

signed short int Range -32768 to 32767

long int 4bytes -2,147,483,647 to 2,147,483,647

signed long int 4bytes same as long int

unsigned long int 4bytes 0 to 4,294,967,295

float 4bytes +/- 3.4e +/- 38 (~7 digits)

double 8bytes +/- 1.7e +/- 308 (~15 digits)

long double 8bytes +/- 1.7e +/- 308 (~15 digits)

wchar_t 2 or 4 bytes 1 wide character

The sizes of variables might be different from those shown in the above table, depending on the compiler and the computer you are using.

Following is the example, which will produce correct size of various data types on your computer.

#include <iostream>

using namespace std;

int main()

{

cout << "Size of char : " << sizeof(char) << endl;

cout << "Size of int : " << sizeof(int) << endl;

cout << "Size of short int : " << sizeof(short int) << endl;

cout << "Size of long int : " << sizeof(long int) << endl;

cout << "Size of float : " << sizeof(float) << endl;

cout << "Size of double : " << sizeof(double) << endl;

cout << "Size of wchar_t : " << sizeof(wchar_t) << endl;

return 0;

Page 9: C++ resumen.pdf

}

This example uses endl, which inserts a new-line character after every line and << operator is being used to pass multiple values out to the screen. We are also using sizeof() function to get size of various data types.

When the above code is compiled and executed, it produces the following result which can vary from machine to machine:

Size of char : 1

Size of int : 4

Size of short int : 2

Size of long int : 4

Size of float : 4

Size of double : 8

Size of wchar_t : 4

typedef Declarations: You can create a new name for an existing type using typedef. Following is the simple syntax to define a new type using typedef:

typedef type newname;

For example, the following tells the compiler that feet is another name for int:

typedef int feet;

Now, the following declaration is perfectly legal and creates an integer variable called distance:

feet distance;

Enumerated Types: An enumerated type declares an optional type name and a set of zero or more identifiers that can be used as values of the type. Each enumerator is a constant whose type is the enumeration.

To create an enumeration requires the use of the keyword enum. The general form of an enumeration type is:

enum enum-name { list of names } var-list;

Here, the enum-name is the enumeration's type name. The list of names is comma separated.

For example, the following code defines an enumeration of colors called colors and the variable c of type color. Finally, c is assigned the value "blue".

enum color { red, green, blue } c;

c = blue;

By default, the value of the first name is 0, the second name has the value 1, the third has the value 2, and so on. But you can give a name a specific value by adding an initializer. For example, in the following enumeration, green will have the value 5.

enum color { red, green=5, blue };

Here, blue will have a value of 6 because each name will be one greater than the one that precedes it.

----------------------------------------------------------------------------------------------------------------------------- ----

Stacks in computing architectures are regions of memory where data is added or removed in a last-in-first-out manner. In most modern computer systems, each thread has a reserved region of memory referred to as its stack. When a function executes, it may add some of its state data to the top of the stack; when the function exits it is responsible for removing that data from the stack. At a minimum, a thread's stack is used to store the location of function calls in order to allow return statements to return to the correct location, but programmers may further choose to explicitly use the stack. If a region of memory lies on the thread's stack, that memory is said to have been allocated on the stack.

Page 10: C++ resumen.pdf

3. Размещение данных в памяти, стек, куча, указатели

• 3. placement of data in memory, stack, heap, pointers

Page 11: C++ resumen.pdf

4. Указатели, взятие адреса, разыменование, косв адресация

• 4. pointers, taking the address, dereferencing, indirect addressing

a pointer is a programming language object, whose value refers to (or "pointsto") another value stored elsewhere in the computer memory using its address. A pointer referencesa location in memory, and obtaining the value stored at that location is known as dereferencing the pointer.

The address of a variable can be obtained by preceding the name of a variable with an

ampersand sign (&), known asaddress-of operator. For example:

foo = &myvar;

This would assign the address of variable myvar to foo; by preceding the name of the

variable myvar with the address-of operator (&), we are no longer assigning the content of the

variable itself to foo, but its address.

The actual address of a variable in memory cannot be known before runtime, but let's assume,

in order to help clarify some concepts, that myvar is placed during runtime in the memory

address 1776.

In this case, consider the following code fragment:

1

2

3

myvar = 25;

foo = &myvar;

bar = myvar;

The values contained in each variable after the execution of this are shown in the following

diagram:

First, we have assigned the value 25 to myvar (a variable whose address in memory we

assumed to be 1776).

The second statement assigns foo the address of myvar, which we have assumed to be 1776.

Finally, the third statement, assigns the value contained in myvar to bar. This is a standard

assignment operation, as already done many times in earlier chapters.

Page 12: C++ resumen.pdf

The main difference between the second and third statements is the appearance of

the address-of operator (&).

The variable that stores the address of another variable (like foo in the previous example) is

what in C++ is called apointer. Pointers are a very powerful feature of the language that has

many uses in lower level programming. A bit later, we will see how to declare and use

pointers.

Dereference operator (*)

As just seen, a variable which stores the address of another variable is called a pointer.

Pointers are said to "point to" the variable whose address they store.

An interesting property of pointers is that they can be used to access the variable they point to

directly. This is done by preceding the pointer name with the dereference operator (*). The

operator itself can be read as "value pointed to by".

Therefore, following with the values of the previous example, the following statement:

baz = *foo;

This could be read as: "baz equal to value pointed to by foo", and the statement would

actually assign the value 25 tobaz, since foo is 1776, and the value pointed to

by 1776 (following the example above) would be 25.

It is important to clearly differentiate that foo refers to the value 1776, while *foo (with an

asterisk * preceding the identifier) refers to the value stored at address 1776, which in this

case is 25. Notice the difference of including or not including the dereference operator (I

have added an explanatory comment of how each of these two expressions could be read):

1

2

baz = foo; // baz equal to foo (1776)

baz = *foo; // baz equal to value pointed to by foo (25)

The reference and dereference operators are thus complementary:

& is the address-of operator, and can be read simply as "address of"

* is the dereference operator, and can be read as "value pointed to by"

Indirect address

Page 13: C++ resumen.pdf

An address that serves as a reference point instead of the

address to the direct location. For example, if a programmer

saved something to an indirect address in memory, the data

is saved to any free spot in the memory, instead of a specific

address.

5. Операторы и операции

5. Operators and operations

Operators Once introduced to variables and constants, we can begin to operate with them by

using operators. What follows is a complete list of operators. At this point, it is likely not

necessary to know all of them, but they are all listed here to also serve as reference.

Assignment operator (=)

The assignment operator assigns a value to a variable.

x = 5;

This statement assigns the integer value 5 to the variable x. The assignment operation always

takes place from right to left, and never the other way around:

x = y;

This statement assigns to variable x the value contained in variable y. The value of x at the

moment this statement is executed is lost and replaced by the value of y.

Consider also that we are only assigning the value of y to x at the moment of the assignment

operation. Therefore, if ychanges at a later moment, it will not affect the new value taken

by x.

For example, let's have a look at the following code - I have included the evolution of the

content stored in the variables as comments:

1

2

3

4

5

6

7

8

9

10

11

// assignment operator

#include <iostream>

using namespace std;

int main ()

{

int a, b; // a:?, b:?

a = 10; // a:10, b:?

b = 4; // a:10, b:4

a = b; // a:4, b:4

b = 7; // a:4, b:7

a:4 b:7 Edit & Run

Page 14: C++ resumen.pdf

12

13

14

15

16

17

cout << "a:";

cout << a;

cout << " b:";

cout << b;

}

This program prints on screen the final values of a and b (4 and 7, respectively). Notice

how a was not affected by the final modification of b, even though we declared a = b earlier.

Assignment operations are expressions that can be evaluated. That means that the assignment

itself has a value, and -for fundamental types- this value is the one assigned in the operation.

For example:

y = 2 + (x = 5);

In this expression, y is assigned the result of adding 2 and the value of another assignment

expression (which has itself a value of 5). It is roughly equivalent to:

1

2

x = 5;

y = 2 + x;

With the final result of assigning 7 to y.

The following expression is also valid in C++:

x = y = z = 5;

It assigns 5 to the all three variables: x, y and z; always from right-to-left.

Arithmetic operators ( +, -, *, /, % )

The five arithmetical operations supported by C++ are:

operator description

+ addition

- subtraction

* multiplication

/ division

% modulo

Operations of addition, subtraction, multiplication and division correspond literally to their

respective mathematical operators. The last one, modulo operator, represented by a

percentage sign (%), gives the remainder of a division of two values. For example:

x = 11 % 3;

results in variable x containing the value 2, since dividing 11 by 3 results in 3, with a

remainder of 2.

Page 15: C++ resumen.pdf

Compound assignment (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)

Compound assignment operators modify the current value of a variable by performing an

operation on it. They are equivalent to assigning the result of an operation to the first

operand:

expression equivalent to...

y += x; y = y + x;

x -= 5; x = x - 5;

x /= y; x = x / y;

price *= units + 1; price = price * (units+1);

and the same for all other compound assignment operators. For example:

1

2

3

4

5

6

7

8

9

10

11

// compound assignment operators

#include <iostream>

using namespace std;

int main ()

{

int a, b=3;

a = b;

a+=2; // equivalent to a=a+2

cout << a;

}

5 Edit & Run

Increment and decrement (++, --)

Some expression can be shortened even more: the increase operator (++) and the decrease

operator (--) increase or reduce by one the value stored in a variable. They are equivalent

to +=1 and to -=1, respectively. Thus:

1

2

3

++x;

x+=1;

x=x+1;

are all equivalent in its functionality; the three of them increase by one the value of x.

In the early C compilers, the three previous expressions may have produced different

executable code depending on which one was used. Nowadays, this type of code optimization

is generally performed automatically by the compiler, thus the three expressions should

produce exactly the same executable code.

A peculiarity of this operator is that it can be used both as a prefix and as a suffix. That

means that it can be written either before the variable name (++x) or after it (x++). Although

in simple expressions like x++ or ++x, both have exactly the same meaning; in other

expressions in which the result of the increment or decrement operation is evaluated, they

may have an important difference in their meaning: In the case that the increase operator is

used as a prefix (++x) of the value, the expression evaluates to the final value of x, once it is

already increased. On the other hand, in case that it is used as a suffix (x++), the value is also

increased, but the expression evaluates to the value that x had before being increased. Notice

the difference:

Page 16: C++ resumen.pdf

Example 1 Example 2

x = 3;

y = ++x;

// x contains 4, y contains 4

x = 3;

y = x++;

// x contains 4, y contains 3

In Example 1, the value assigned to y is the value of x after being increased. While

in Example 2, it is the value x had before being increased.

Relational and comparison operators ( ==, !=, >, <, >=, <= )

Two expressions can be compared using relational and equality operators. For example, to

know if two values are equal or if one is greater than the other.

The result of such an operation is either true or false (i.e., a Boolean value).

The relational operators in C++ are:

operator description

== Equal to

!= Not equal to

< Less than

> Greater than

<= Less than or equal to

>= Greater than or equal to

Here there are some examples:

1

2

3

4

5

(7 == 5) // evaluates to false

(5 > 4) // evaluates to true

(3 != 2) // evaluates to true

(6 >= 6) // evaluates to true

(5 < 5) // evaluates to false

Of course, it's not just numeric constants that can be compared, but just any value, including,

of course, variables. Suppose that a=2, b=3 and c=6, then:

1

2

3

4

(a == 5) // evaluates to false, since a is not equal to 5

(a*b >= c) // evaluates to true, since (2*3 >= 6) is true

(b+4 > a*c) // evaluates to false, since (3+4 > 2*6) is false

((b=2) == a) // evaluates to true

Be careful! The assignment operator (operator =, with one equal sign) is not the same as the

equality comparison operator (operator ==, with two equal signs); the first one (=) assigns the

value on the right-hand to the variable on its left, while the other (==) compares whether the

values on both sides of the operator are equal. Therefore, in the last expression ((b=2) ==

a), we first assigned the value 2 to b and then we compared it to a (that also stores the value

2), yielding true.

Logical operators ( !, &&, || )

The operator ! is the C++ operator for the Boolean operation NOT. It has only one operand,

to its right, and inverts it, producing false if its operand is true, and true if its operand

Page 17: C++ resumen.pdf

is false. Basically, it returns the opposite Boolean value of evaluating its operand. For

example:

1

2

3

4

!(5 == 5) // evaluates to false because the expression at its right (5

== 5) is true

!(6 <= 4) // evaluates to true because (6 <= 4) would be false

!true // evaluates to false

!false // evaluates to true

The logical operators && and || are used when evaluating two expressions to obtain a single

relational result. The operator&& corresponds to the Boolean logical operation AND, which

yields true if both its operands are true, and false otherwise. The following panel shows

the result of operator && evaluating the expression a&&b:

&& OPERATOR (and)

a b a && b

true true true

true false false

false true false

false false false

The operator || corresponds to the Boolean logical operation OR, which yields true if either

of its operands is true, thus being false only when both operands are false. Here are the

possible results of a||b:

|| OPERATOR (or)

a b a || b

true true true

true false true

false true true

false false false

For example:

1

2

( (5 == 5) && (3 > 6) ) // evaluates to false ( true && false )

( (5 == 5) || (3 > 6) ) // evaluates to true ( true || false )

When using the logical operators, C++ only evaluates what is necessary from left to right to

come up with the combined relational result, ignoring the rest. Therefore, in the last example

((5==5)||(3>6)), C++ evaluates first whether 5==5 istrue, and if so, it never checks

whether 3>6 is true or not. This is known as short-circuit evaluation, and works like this for

these operators:

operator short-circuit

&& if the left-hand side expression is false, the combined result is false (the right-hand

side expression is never evaluated).

|| if the left-hand side expression is true, the combined result is true (the right-hand

side expression is never evaluated).

This is mostly important when the right-hand expression has side effects, such as altering

values:

if ( (i<10) && (++i<n) ) { /*...*/ } // note that the condition

increments i

Page 18: C++ resumen.pdf

Here, the combined conditional expression would increase i by one, but only if the condition

on the left of && is true, because otherwise, the condition on the right-hand side (++i<n) is

never evaluated.

Conditional ternary operator ( ? )

The conditional operator evaluates an expression, returning one value if that expression

evaluates to true, and a different one if the expression evaluates as false. Its syntax is:

condition ? result1 : result2

If condition is true, the entire expression evaluates to result1, and otherwise to result2.

1

2

3

4

7==5 ? 4 : 3 // evaluates to 3, since 7 is not equal to 5.

7==5+2 ? 4 : 3 // evaluates to 4, since 7 is equal to 5+2.

5>3 ? a : b // evaluates to the value of a, since 5 is greater than

3.

a>b ? a : b // evaluates to whichever is greater, a or b.

For example:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// conditional operator

#include <iostream>

using namespace std;

int main ()

{

int a,b,c;

a=2;

b=7;

c = (a>b) ? a : b;

cout << c << '\n';

}

7 Edit & Run

In this example, a was 2, and b was 7, so the expression being evaluated (a>b) was not true,

thus the first value specified after the question mark was discarded in favor of the second

value (the one after the colon) which was b (with a value of 7).

Comma operator ( , )

The comma operator (,) is used to separate two or more expressions that are included where

only one expression is expected. When the set of expressions has to be evaluated for a value,

only the right-most expression is considered.

For example, the following code:

a = (b=3, b+2);

would first assign the value 3 to b, and then assign b+2 to variable a. So, at the end,

variable a would contain the value 5 while variable b would contain value 3.

Page 19: C++ resumen.pdf

Bitwise operators ( &, |, ^, ~, <<, >> )

Bitwise operators modify variables considering the bit patterns that represent the values they

store.

operator asm equivalent description

& AND Bitwise AND

| OR Bitwise inclusive OR

^ XOR Bitwise exclusive OR

~ NOT Unary complement (bit inversion)

<< SHL Shift bits left

>> SHR Shift bits right

Explicit type casting operator

Type casting operators allow to convert a value of a given type to another type. There are

several ways to do this in C++. The simplest one, which has been inherited from the C

language, is to precede the expression to be converted by the new type enclosed between

parentheses (()):

1

2

3

int i;

float f = 3.14;

i = (int) f;

The previous code converts the floating-point number 3.14 to an integer value (3); the

remainder is lost. Here, the typecasting operator was (int). Another way to do the same

thing in C++ is to use the functional notation preceding the expression to be converted by the

type and enclosing the expression between parentheses:

i = int (f);

Both ways of casting types are valid in C++.

sizeof

This operator accepts one parameter, which can be either a type or a variable, and returns the

size in bytes of that type or object:

x = sizeof (char);

Here, x is assigned the value 1, because char is a type with a size of one byte.

The value returned by sizeof is a compile-time constant, so it is always determined before

program execution.

Other operators

Later in these tutorials, we will see a few more operators, like the ones referring to pointers or

the specifics for object-oriented programming.

Page 20: C++ resumen.pdf

Precedence of operators

A single expression may have multiple operators. For example:

x = 5 + 7 % 2;

In C++, the above expression always assigns 6 to variable x, because the % operator has a

higher precedence than the +operator, and is always evaluated before. Parts of the expressions

can be enclosed in parenthesis to override this precedence order, or to make explicitly clear

the intended effect. Notice the difference:

1

2

x = 5 + (7 % 2); // x = 6 (same as without parenthesis)

x = (5 + 7) % 2; // x = 0

From greatest to smallest priority, C++ operators are evaluated in the following order: Level Precedence group Operator Description Grouping

1 Scope :: scope qualifier Left-to-right

2 Postfix (unary)

++ -- postfix increment / decrement

Left-to-right

() functional forms

[] subscript

. -> member access

3 Prefix (unary)

++ -- prefix increment / decrement

Right-to-left

~ ! bitwise NOT / logical NOT

+ - unary prefix

& * reference / dereference

new delete allocation / deallocation

sizeof parameter pack

(type) C-style type-casting

4 Pointer-to-member .* ->* access pointer Left-to-right

5 Arithmetic: scaling * / % multiply, divide, modulo Left-to-right

6 Arithmetic: addition + - addition, subtraction Left-to-right

7 Bitwise shift << >> shift left, shift right Left-to-right

8 Relational < > <= >= comparison operators Left-to-right

9 Equality == != equality / inequality Left-to-right

10 And & bitwise AND Left-to-right

11 Exclusive or ^ bitwise XOR Left-to-right

12 Inclusive or | bitwise OR Left-to-right

13 Conjunction && logical AND Left-to-right

14 Disjunction || logical OR Left-to-right

15 Assignment-level expressions

= *= /= %= +=

-=

>>= <<= &= ^=

|=

assignment / compound assignment

Right-to-left

Page 21: C++ resumen.pdf

?: conditional operator

16 Sequencing , comma separator Left-to-right

When an expression has two operators with the same precedence level, grouping determines

which one is evaluated first: either left-to-right or right-to-left.

11.Scope

A scope is a region of the program and broadly speaking there are three places, where variables can be declared:

Inside a function or a block which is called local variables,

In the definition of function parameters which is called formal parameters.

Outside of all functions which is called global variables.

We will learn what is a function and it's parameter in subsequent chapters. Here let us explain what are local and global variables.

6. Массивы, освобождение массива

• 6. Arrays, release the array

Arrays An array is a series of elements of the same type placed in contiguous memory locations that

can be individually referenced by adding an index to a unique identifier.

That means that, for example, five values of type int can be declared as an array without

having to declare 5 different variables (each with its own identifier). Instead, using an array,

the five int values are stored in contiguous memory locations, and all five can be accessed

using the same identifier, with the proper index.

For example, an array containing 5 integer values of type int called foo could be represented

as:

where each blank panel represents an element of the array. In this case, these are values of

type int. These elements are numbered from 0 to 4, being 0 the first and 4 the last; In C++,

the first element in an array is always numbered with a zero (not a one), no matter its length.

Like a regular variable, an array must be declared before it is used. A typical declaration for

an array in C++ is:

type name [elements];

where type is a valid type (such as int, float...), name is a valid identifier and

the elements field (which is always enclosed in square brackets []), specifies the length of

the array in terms of the number of elements.

Page 22: C++ resumen.pdf

Therefore, the foo array, with five elements of type int, can be declared as:

int foo [5];

NOTE: The elements field within square brackets [], representing the number of

elements in the array, must be aconstant expression, since arrays are blocks of static

memory whose size must be determined at compile time, before the program runs.

int foo [5] = { 16, 2, 77, 40, 12071 };

Multidimensional arrays

Multidimensional arrays can be described as "arrays of arrays". For example, a bidimensional

array can be imagined as a two-dimensional table made of elements, all of them of a same

uniform data type.

jimmy represents a bidimensional array of 3 per 5 elements of type int. The C++ syntax for

this is:

int jimmy [3][5];

and, for example, the way to reference the second element vertically and fourth horizontally

in an expression would be:

jimmy[1][3]

(remember that array indices always begin with zero).

Multidimensional arrays are not limited to two indices (i.e., two dimensions). They can

contain as many indices as needed. Although be careful: the amount of memory needed for an

array increases exponentially with each dimension. For example:

char century [100][365][24][60][60];

declares an array with an element of type char for each second in a century. This amounts to

more than 3 billion char! So this declaration would consume more than 3 gigabytes of

memory!

Page 23: C++ resumen.pdf

At the end, multidimensional arrays are just an abstraction for programmers, since the same

results can be achieved with a simple array, by multiplying its indices:

1

2

int jimmy [3][5]; // is equivalent to

int jimmy [15]; // (3 * 5 = 15)

With the only difference that with multidimensional arrays, the compiler automatically

remembers the depth of each imaginary dimension. The following two pieces of code

produce the exact same result, but one uses a bidimensional array while the other uses a

simple array:

multidimensional array pseudo-multidimensional array

#define WIDTH 5

#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];

int n,m;

int main ()

{

for (n=0; n<HEIGHT; n++)

for (m=0; m<WIDTH; m++)

{

jimmy[n][m]=(n+1)*(m+1);

}

}

#define WIDTH 5

#define HEIGHT 3

int jimmy [HEIGHT * WIDTH];

int n,m;

int main ()

{

for (n=0; n<HEIGHT; n++)

for (m=0; m<WIDTH; m++)

{

jimmy[n*WIDTH+m]=(n+1)*(m+1);

}

}

None of the two code snippets above produce any output on the screen, but both assign

values to the memory block called jimmy in the following way:

Note that the code uses defined constants for the width and height, instead of using directly

their numerical values. This gives the code a better readability, and allows changes in the

code to be made easily in one place.

Arrays as parameters

At some point, we may need to pass an array to a function as a parameter. In C++, it is not

possible to pass the entire block of memory represented by an array to a function directly as

an argument. But what can be passed instead is its address. In practice, this has almost the

same effect, and it is a much faster and more efficient operation.

To accept an array as parameter for a function, the parameters can be declared as the array

type, but with empty brackets, omitting the actual size of the array. For example:

void procedure (int arg[])

This function accepts a parameter of type "array of int" called arg. In order to pass to this

function an array declared as:

Page 24: C++ resumen.pdf

int myarray [40];

it would be enough to write a call like this:

procedure (myarray);

Here you have a complete example:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// arrays as parameters

#include <iostream>

using namespace std;

void printarray (int arg[], int length) {

for (int n=0; n<length; ++n)

cout << arg[n] << ' ';

cout << '\n';

}

int main ()

{

int firstarray[] = {5, 10, 15};

int secondarray[] = {2, 4, 6, 8, 10};

printarray (firstarray,3);

printarray (secondarray,5);

}

5 10 15

2 4 6 8 10

Edit & Run

In the code above, the first parameter (int arg[]) accepts any array whose elements are of

type int, whatever its length. For that reason, we have included a second parameter that tells

the function the length of each array that we pass to it as its first parameter. This allows the

for loop that prints out the array to know the range to iterate in the array passed, without

going out of range.

In a function declaration, it is also possible to include multidimensional arrays. The format

for a tridimensional array parameter is:

base_type[][depth][depth]

For example, a function with a multidimensional array as argument could be:

void procedure (int myarray[][3][4])

Notice that the first brackets [] are left empty, while the following ones specify sizes for

their respective dimensions. This is necessary in order for the compiler to be able to

determine the depth of each additional dimension.

In a way, passing an array as argument always loses a dimension. The reason behind is that,

for historical reasons, arrays cannot be directly copied, and thus what is really passed is a

pointer. This is a common source of errors for novice programmers. Although a clear

understanding of pointers, explained in a coming chapter, helps a lot.

Page 25: C++ resumen.pdf

Library arrays

The arrays explained above are directly implemented as a language feature, inherited from

the C language. They are a great feature, but by restricting its copy and easily decay into

pointers, they probably suffer from an excess of optimization.

To overcome some of these issues with language built-in arrays, C++ provides an alternative

array type as a standard container. It is a type template (a class template, in fact) defined in

header <array>.

Containers are a library feature that falls out of the scope of this tutorial, and thus the class

will not be explained in detail here. Suffice it to say that they operate in a similar way to

built-in arrays, except that they allow being copied (an actually expensive operation that

copies the entire block of memory, and thus to use with care) and decay into pointers only

when explicitly told to do so (by means of its member data).

Just as an example, these are two versions of the same example using the language built-in

array described in this chapter, and the container in the library:

language built-in array container library array

#include <iostream>

using namespace std;

int main()

{

int myarray[3] = {10,20,30};

for (int i=0; i<3; ++i)

++myarray[i];

for (int elem : myarray)

cout << elem << '\n';

}

#include <iostream>

#include <array>

using namespace std;

int main()

{

array<int,3> myarray {10,20,30};

for (int i=0; i<myarray.size(); ++i)

++myarray[i];

for (int elem : myarray)

cout << elem << '\n';

}

As you can see, both kinds of arrays use the same syntax to access its

elements: myarray[i]. Other than that, the main differences lay on the declaration of the

array, and the inclusion of an additional header for the library array. Notice also how it

is easy to access the size of the library array.

Operator delete[]

Deallocate storage space of array

Page 26: C++ resumen.pdf

8. Произвольное количество параметров в функции

8. arbitrary number of parameters in the function

In C++, two different functions can have the same name if their parameters are different; either

because they have a different number of parameters, or because any of their parameters are of a

different type. For example:

For cases such as this, C++ has the ability to define functions with generic types, known

as function templates. Defining a function template follows the same syntax than a regular

function, except that it is preceded by the template keyword and a series of template

parameters enclosed in angle-brackets <>:

template <template-parameters> function-declaration

The template parameters are a series of parameters separated by commas. These parameters

can be generic template types by specifying either the class or typename keyword followed

Page 27: C++ resumen.pdf

by an identifier. This identifier can then be used in the function declaration as if it was a

regular type. For example, a generic sum function could be defined as:

1

2

3

4

5

template <class SomeType>

SomeType sum (SomeType a, SomeType b)

{

return a+b; }

Page 28: C++ resumen.pdf

9. if, while, for, switch

Syntax:

(selection statement) The syntax of an if...else if...else statement in C++ is:

if(boolean_expression 1)

{

// Executes when the boolean expression 1 is true

}

else if( boolean_expression 2)

{

// Executes when the boolean expression 2 is true

}

else if( boolean_expression 3)

{

// Executes when the boolean expression 3 is true

}

else

{

// executes when the none of the above condition is true.

}

(Iteration Statement) Loops repeat a statement a certain number of times, or while a condition is fulfilled. They are

introduced by the keywordswhile, do, and for.

The while loop

The simplest kind of loop is the while-loop. Its syntax is:

while (expression) statement

The while-loop simply repeats statement while expression is true. If, after any execution

of statement, expression is no longer true, the loop ends, and the program continues right

after the loop. For example, let's have a look at a countdown using a while-loop:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// custom countdown using while

#include <iostream>

using namespace std;

int main ()

{

int n = 10;

while (n>0) {

cout << n << ", ";

--n;

}

cout << "liftoff!\n";

}

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

A switch statement allows a variable to be tested for equality against a list of values. Each value is called a case, and the variable being switched on is checked for each case.

Syntax: The syntax for a switch statement in C++ is as follows:

Page 29: C++ resumen.pdf

switch(expression){

case constant-expression :

statement(s);

break; //optional

case constant-expression :

statement(s);

break; //optional

// you can have any number of case statements.

default : //Optional

statement(s);

}

Page 30: C++ resumen.pdf

10. Описание класса

• 10. class description

#pragma once #include <string> #include <vector> using namespace std; #ifndef H_BANK #define H_BANK //Indicate that there exist a class called AccountHolder, //but we don't want to use #include because we may be //creating circular references class AccountHolder; class Bank { public: Bank(string name, double initial_amount = 0.0) { m_bank_name = name; m_bank_money = initial_amount; } ~Bank(void) {} string get_bank_name() { return m_bank_name; } int get_bank_id() { return m_bank_id; } void AddNewCustomer(AccountHolder* customer) { m_customer_list.push_back(customer); } void DeleteCustomer(string customer_name); AccountHolder* GetCustomer(string customer_name); void displayCustomers(); void displayCustomersWithBalance(); private: //Balance on bank accounts affect the money on the bank //so, we need to make BankAccount a "friend class" so that //it will be able to change the bank money, which is private friend class BankAccount; int m_bank_id; string m_bank_name; double m_bank_money; bool Deposit(double amount) { if (amount <= 0.0) return false; m_bank_money += amount; return true; } bool Withdraw(double amount)

Page 31: C++ resumen.pdf

{ if (amount <= 0.0) return false; if (m_bank_money < amount) return false; m_bank_money -= amount; return true; } vector<AccountHolder*> m_customer_list; }; #endif

Classes & Objects in Detail: So far, you have got very basic idea about C++ Classes and Objects. There are further interesting concepts related to C++ Classes and Objects which we will discuss in various sub-sections listed below:

Concept Description

Class member functions

A member function of a class is a function that has its

definition or its prototype within the class definition like any

other variable.

Class access modifiers

A class member can be defined as public, private or

protected. By default members would be assumed as private.

Constructor & destructor

A class constructor is a special function in a class that is

called when a new object of the class is created. A destructor

is also a special function which is called when created object

is deleted.

C++ copy constructor

The copy constructor is a constructor which creates an object

by initializing it with an object of the same class, which has

been created previously.

C++ friend functions

A friend function is permitted full access to private and

protected members of a class.

C++ inline functions

With an inline function, the compiler tries to expand the code

in the body of the function in place of a call to the function.

The this pointer in C++

Every object has a special pointer this which points to the

object itself.

Pointer to C++ classes

A pointer to a class is done exactly the same way a pointer to

a structure is. In fact a class is really just a structure with

functions in it.

Static members of a class

Both data members and function members of a class can be

declared as static.

11. Области видимости членов класса

• 11. Scopes class members

Page 32: C++ resumen.pdf

Classes have the same format as plain data structures, except that they can also include

functions and have these new things called access specifiers. An access specifier is one of the

following three keywords: private, public or protected. These specifiers modify the

access rights for the members that follow them:

private members of a class are accessible only from within other members of the

same class (or from their"friends").

protected members are accessible from other members of the same class (or from

their "friends"), but also from members of their derived classes.

Finally, public members are accessible from anywhere where the object is visible.

By default, all members of a class declared with the class keyword have private access for

all its members. Therefore, any member that is declared before any other access specifier has

private access automatically. For example:

1

2

3

4

5

6

class Rectangle {

int width, height;

public:

void set_values (int,int);

int area (void);

} rect;

15. Constructors, destructors.

Parameterized Constructor: A default constructor does not have any parameter, but if you need, a constructor can have parameters. This helps you to assign initial value to an object at the time of its creation as shown in the following example:

#pragma once #include <string> #include <vector> using namespace std; #ifndef H_BANK #define H_BANK //Indicate that there exist a class called AccountHolder, //but we don't want to use #include because we may be //creating circular references class AccountHolder; class Bank { public: Bank(string name, double initial_amount = 0.0) { m_bank_name = name; m_bank_money = initial_amount; } ~Bank(void) {} string get_bank_name() { return m_bank_name; } int get_bank_id() { return m_bank_id; }

Page 33: C++ resumen.pdf

A destructor is a special member function that is called when the lifetime of an object ends. The purpose of the destructor is to free the resources that the object may have acquired

during its lifetime.

The destructor is commonly used to "clean up" when an object is no longer necessary. Consider the

following declaration of a String class:

// spec1_destructors.cpp

#include <string.h>

class String {

public:

String( char *ch ); // Declare constructor

~String(); // and destructor.

private:

char *_text;

size_t sizeOfText;

};

// Define the constructor.

String::String( char *ch ) {

sizeOfText = strlen( ch ) + 1;

// Dynamically allocate the correct amount of memory.

_text = new char[ sizeOfText ];

// If the allocation succeeds, copy the initialization string.

if( _text )

strcpy_s( _text, sizeOfText, ch );

}

// Define the destructor.

String::~String() {

// Deallocate the memory that was previously reserved

// for this string.

if (_text)

delete[] _text;

}

int main() {

String str("The piper in the glen...");

}

In the preceding example, the destructor String::~String uses the delete operator to deallocate

the space dynamically allocated for text storage.

Page 34: C++ resumen.pdf

22) Friend Functions and Friend Classes

Friendship and inheritance

Friend functions

In principle, private and protected members of a class cannot be accessed from outside the

same class in which they are declared. However, this rule does not apply to "friends".

Friends are functions or classes declared with the friend keyword.

A non-member function can access the private and protected members of a class if it is

declared a friend of that class. That is done by including a declaration of this external

function within the class, and preceding it with the keywordfriend:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// friend functions

#include <iostream>

using namespace std;

class Rectangle {

int width, height;

public:

Rectangle() {}

Rectangle (int x, int y) : width(x),

height(y) {}

int area() {return width * height;}

friend Rectangle duplicate (const

Rectangle&);

};

Rectangle duplicate (const Rectangle&

param)

{

Rectangle res;

res.width = param.width*2;

res.height = param.height*2;

return res;

}

int main () {

Rectangle foo;

Rectangle bar (2,3);

foo = duplicate (bar);

cout << foo.area() << '\n';

return 0;

}

24 Edit & Run

The duplicate function is a friend of class Rectangle. Therefore, function duplicate is

able to access the members widthand height (which are private) of different objects of

type Rectangle. Notice though that neither in the declaration ofduplicate nor in its later

use in main, member function duplicate is considered a member of class Rectangle. It

isn't! It simply has access to its private and protected members without being a member.

Typical use cases of friend functions are operations that are conducted between two different

classes accessing private or protected members of both.

Page 35: C++ resumen.pdf

Friend classes

Similar to friend functions, a friend class is a class whose members have access to the private

or protected members of another class:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

// friend class

#include <iostream>

using namespace std;

class Square;

class Rectangle {

int width, height;

public:

int area ()

{return (width * height);}

void convert (Square a);

};

class Square {

friend class Rectangle;

private:

int side;

public:

Square (int a) : side(a) {}

};

void Rectangle::convert (Square a) {

width = a.side;

height = a.side;

}

int main () {

Rectangle rect;

Square sqr (4);

rect.convert(sqr);

cout << rect.area();

return 0;

}

16 Edit & Run

In this example, class Rectangle is a friend of class Square allowing Rectangle's member

functions to access private and protected members of Square. More

concretely, Rectangle accesses the member variable Square::side, which describes the

side of the square.

There is something else new in this example: at the beginning of the program, there is an

empty declaration of classSquare. This is necessary because

class Rectangle uses Square (as a parameter in member convert),

and Square usesRectangle (declaring it a friend).

Friendships are never corresponded unless specified: In our example, Rectangle is

considered a friend class by Square, but Square is not considered a friend by Rectangle.

Therefore, the member functions of Rectangle can access the protected and private members

of Square but not the other way around. Of course, Square could also be declared friend

ofRectangle, if needed, granting such an access.

Another property of friendships is that they are not transitive: The friend of a friend is not

considered a friend unless explicitly specified.

Page 36: C++ resumen.pdf

• 29. syntax exception handling

• 30. Syntax throwing exceptions

Throwing an Exception One way of handling complex error conditions is with exceptions. An exception is a value

or an object that signals an error. When the error occurs, an exception is said to be

“thrown” because control will pass to a part of the program that catches and handles

that

type of error. For example, the following code shows the divide function, modified to

throw an exception when division by zero has been attempted. double divide(double numerator, double denominator) { if (denominator == 0) throw "ERROR: Cannot divide by zero.\n"; else return numerator / denominator; }

The following statement causes the exception to be thrown. throw "ERROR: Cannot divide by zero.\n";

The throw key word is followed by an argument, which can be any value. As you will see,

the type of the argument is used to determine the nature of the error. The function above

simply throws a string containing an error message.

The line containing a throw statement is known as the throw point. When a throw statement

is executed, control is passed to another part of the program known as an exception

handler.

Handling an Exception To handle an exception, a program must have a try/catch construct. The general format of

the try/catch construct is try

{ // code here calls functions or object member // functions that might throw an exception. } catch(exception parameter) { // code here handles the exception }

// Repeat as many catch blocks as needed.

The first part of the construct is the try block. This starts with the key word try and is

followed

by a block of code executing any statements that might directly or indirectly cause

an exception to be thrown. The try block is immediately followed by one or more catch

blocks, which are the exception handlers. A catch block starts with the key word catch,

followed by a set of parentheses containing the declaration of an exception parameter. For

example, here is a try/catch construct that can be used with the divide function: try { quotient = divide(num1, num2); cout << "The quotient is " << quotient << endl; }

catch (char *exceptionString) { cout << exceptionString; }

Page 37: C++ resumen.pdf
Page 38: C++ resumen.pdf
Page 39: C++ resumen.pdf
Page 40: C++ resumen.pdf

• 32. Constructors and Exceptions

Extracting Information from the Exception Class

Page 41: C++ resumen.pdf
Page 42: C++ resumen.pdf

• 31. Standard exclusions

Page 43: C++ resumen.pdf

12. inheritance (classes)

Inheritance and the Is-a Relationship When one object is a specialized version of another object, there is an is-a relationship

between them. For example, a grasshopper is an insect. Here are a few other examples of

the is-a relationship.

• A poodle is a dog.

• A car is a vehicle.

• A rectangle is a shape.

Page 44: C++ resumen.pdf

13. Multiple Inheritance

#include <iostream>

using std::ostream;

using std::cout;

using std::endl;

class Base1 {

public:

Base1( int parameterValue )

{

value = parameterValue;

}

int getData() const

{

return value;

}

protected:

int value;

};

class Base2

{

public:

Base2( char characterData )

{

letter = characterData;

Page 45: C++ resumen.pdf

}

char getData() const

{

return letter;

}

protected:

char letter;

};

class Derived : public Base1, public Base2

{

public:

Derived( int integer, char character, double double1 )

: Base1( integer ), Base2( character ), real( double1 ) { }

double getReal() const {

return real;

}

void display()

{

cout << " Integer: " << value << "\n Character: "

<< letter << "\nReal number: " << real;

}

private:

double real;

};

int main()

{

Base1 base1( 10 ), *base1Ptr = 0;

Base2 base2( 'Z' ), *base2Ptr = 0;

Derived derived( 7, 'A', 3.5 );

cout << base1.getData()

<< base2.getData();

derived.display();

cout << derived.Base1::getData()

<< derived.Base2::getData()

<< derived.getReal() << "\n\n";

base1Ptr = &derived;

cout << base1Ptr->getData() << '\n';

base2Ptr = &derived;

cout << base2Ptr->getData() << endl;

return 0;

}

10Z Integer: 7

Character: A

Real number: 3.57A3.5

7

A

Page 46: C++ resumen.pdf

14.virtual inheritance

The "diamond problem" (sometimes referred to as the "deadly diamond of death" [5]) is an

ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B

and C. If there is a method in A that B and/or C hasoverridden, and D does not override it, then

which version of the method does D inherit: that of B, or that of C?

#include <iostream> using namespace std; class Animal{ public: int age; void walk() { cout<<"animal walks"<<endl; } }; class Tiger : public Animal { }; class Lion : public Animal { }; class Liger: public Tiger, public Lion { }; int main() { Liger anil; anil.walk(); // is ambigious error! return 0; }

Deadly Diamond problem

Check theconstructor call too! How it’s call all of them

#include <iostream> using namespace std; class Animal{ public: int age; void walk() {

Page 47: C++ resumen.pdf

cout<<"animal walks"<<endl; } }; class Tiger : virtual public Animal { public: Tiger() { cout<<"constructor of tiger"<<endl; } }; class Lion :virtual public Animal { public: Lion() { cout<<"constructor of Lion"<<endl; } }; class Liger: public Tiger, public Lion { }; int main() { Liger anil; anil.walk(); getchar(); return 0; }

Page 48: C++ resumen.pdf

Polymorphism The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.

C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.

Consider the following example where a base class has been derived by other two classes:

#include <iostream>

using namespace std;

class Shape {

protected:

int width, height;

public:

Shape( int a=0, int b=0)

{

width = a;

height = b;

}

int area()

{

cout << "Parent class area :" <<endl;

return 0;

}

};

class Rectangle: public Shape{

public:

Rectangle( int a=0, int b=0):Shape(a, b) { }

int area ()

{

cout << "Rectangle class area :" <<endl;

return (width * height);

}

};

class Triangle: public Shape{

public:

Triangle( int a=0, int b=0):Shape(a, b) { }

int area ()

{

cout << "Triangle class area :" <<endl;

return (width * height / 2);

}

};

// Main function for the program

int main( )

{

Shape *shape;

Rectangle rec(10,7);

Triangle tri(10,5);

// store the address of Rectangle

shape = &rec;

// call rectangle area.

shape->area();

// store the address of Triangle

shape = &tri;

// call triangle area.

shape->area();

return 0;

}

Page 49: C++ resumen.pdf

When the above code is compiled and executed, it produces the following result:

Parent class area

Parent class area

The reason for the incorrect output is that the call of the function area() is being set once by the compiler as the version defined in the base class. This is called static resolution of the function call, or static linkage - the function call is fixed before the program is executed. This is also sometimes called early binding because the area() function is set during the compilation of the program. But now, let's make a slight modification in our program and precede the declaration of area() in the Shape class with the keyword virtual so that it looks like this:

class Shape {

protected:

int width, height;

public:

Shape( int a=0, int b=0)

{

width = a;

height = b;

}

virtual int area()

{

cout << "Parent class area :" <<endl;

return 0;

}

};

After this slight modification, when the previous example code is compiled and executed, it produces the following result:

Rectangle class area

Triangle class area

This time, the compiler looks at the contents of the pointer instead of it's type. Hence, since addresses of objects of tri and rec classes are stored in *shape the respective area() function is called.

As you can see, each of the child classes has a separate implementation for the function area(). This is how polymorphism is generally used. You have different classes with a function of the same name, and even the same parameters, but with different implementations.

Virtual Function: A virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don't want static linkage for this function. What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.

Pure Virtual Functions: It's possible that you'd want to include a virtual function in a base class so that it may be redefined in a derived class to suit the objects of that class, but that there is no meaningful definition you could give for the function in the base class.

We can change the virtual function area() in the base class to the following:

class Shape {

protected:

int width, height;

public:

Shape( int a=0, int b=0)

{

width = a;

height = b;

}

// pure virtual function

virtual int area() = 0;

};

The = 0 tells the compiler that the function has no body and above virtual function will be called pure virtual function.

Page 50: C++ resumen.pdf