C++ TUTORIAL.docx

download C++ TUTORIAL.docx

of 122

Transcript of C++ TUTORIAL.docx

C++ MANUAL TUTORIALStructure of a programThe best way to learn a programming language is by writing programs. Typically, the first program beginners write is a program called "Hello World", which simply prints "Hello World" to your computer screen. Although it is very simple, it contains all the fundamental components C++ programs have:1234567// my first program in C++#include

int main(){ std::cout = 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 value2toband then we compared it toa(that also stores the value 2), yieldingtrue.

Logical operators ( !, &&, || )The operator!is the C++ operator for the Boolean operation NOT. It has only one operand, to its right, and inverts it, producingfalseif its operand istrue, andtrueif its operand isfalse. Basically, it returns the opposite Boolean value of evaluating its operand. For example:1234!(5 == 5) // evaluates to false because the expression at its right (5 == 5) is true!(6 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 whether5==5istrue, and if so, it never checks whether3>6istrueor not. This is known asshort-circuit evaluation, and works like this for these operators:operatorshort-circuit

&&if the left-hand side expression isfalse, the combined result isfalse(the right-hand side expression is never evaluated).

||if the left-hand side expression istrue, the combined result istrue(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 ( (ib) ? a : b;

cout member access

3Prefix (unary)++ --prefix increment / decrementRight-to-left

~ !bitwise NOT / logical NOT

+ -unary prefix

& *reference / dereference

new deleteallocation / deallocation

sizeofparameter pack

(type)C-style type-casting

4Pointer-to-member.* ->*access pointerLeft-to-right

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

6Arithmetic: addition+ -addition, subtractionLeft-to-right

7Bitwise shift>shift left, shift rightLeft-to-right

8Relational< > =comparison operatorsLeft-to-right

9Equality== !=equality / inequalityLeft-to-right

10And&bitwise ANDLeft-to-right

11Exclusive or^bitwise XORLeft-to-right

12Inclusive or|bitwise ORLeft-to-right

13Conjunction&&logical ANDLeft-to-right

14Disjunction||logical ORLeft-to-right

15Assignment-level expressions= *= /= %= += -=>>= > myint;

This declares astringwith initialized to a value of"1204", and a variable of typeint. Then, the third line uses this variable to extract from astringstreamconstructed from the string. This piece of code stores the numerical value1204in the variable calledmyint.123456789101112131415161718192021// stringstreams#include #include #include using namespace std;

int main (){ string mystr; float price=0; int quantity=0;

cout > price; cout > quantity; cout 0; n--) { if (n==5) continue; cout ):12345678910111213141516171819202122232425262728293031// pointers to structures#include #include #include using namespace std;

struct movies_t { string title; int year;};

int main (){ string mystr;

movies_t amovie; movies_t * pmovie; pmovie = &amovie;

cout title); cout > pmovie->year;

cout titleand(*pmovie).titleare valid, and both access the membertitleof the data structure pointed by a pointer calledpmovie. It is definitely something different than:*pmovie.title

which is rather equivalent to:*(pmovie.title)

This would access the value pointed by a hypothetical pointer member calledtitleof the structure objectpmovie(which is not the case, sincetitleis not a pointer type). The following panel summarizes possible combinations of the operators for pointers and for structure members:ExpressionWhat is evaluatedEquivalent

a.bMemberbof objecta

a->bMemberbof object pointed to bya(*a).b

*a.bValue pointed to by memberbof objecta*(a.b)

Nesting structuresStructures can also be nested in such a way that an element of a structure is itself another structure:123456789101112struct movies_t { string title; int year;};

struct friends_t { string name; string email; movies_t favorite_movie;} charlie, maria;

friends_t * pfriends = &charlie;

After the previous declarations, all of the following expressions would be valid:1234charlie.namemaria.favorite_movie.titlecharlie.favorite_movie.yearpfriends->favorite_movie.year

(where, by the way, the last two expressions refer to the same member).

Other data typesType aliases (typedef / using)A type alias is a different name by which a type can be identified. In C++, any valid type can be aliased so that it can be referred to with a different identifier.

In C++, there are two syntaxes for creating such type aliases: The first, inherited from the C language, uses thetypedefkeyword:

typedef existing_type new_type_name ;

whereexisting_typeis any type, either fundamental or compound, andnew_type_nameis an identifier with the new name given to the type.

For example:1234typedef char C;typedef unsigned int WORD;typedef char * pChar;typedef char field [50];

This defines four type aliases:C,WORD,pChar, andfieldaschar,unsigned int,char*andchar[50], respectively. Once these aliases are defined, they can be used in any declaration just like any other valid type:1234C mychar, anotherchar, *ptc1;WORD myword;pChar ptc2;field name;

More recently, a second syntax to define type aliases was introduced in the C++ language:using new_type_name = existing_type ;

For example, the same type aliases as above could be defined as:1234using C = char;using WORD = unsigned int;using pChar = char *;using field = char [50];

Both aliases defined withtypedefand aliases defined withusingare semantically equivalent. The only difference being thattypedefhas certain limitations in the realm of templates thatusinghas not. Therefore,usingis more generic, althoughtypedefhas a longer history and is probably more common in existing code.

Note that neithertypedefnorusingcreate new distinct data types. They only create synonyms of existing types. That means that the type ofmywordabove, declared with typeWORD, can as well be considered of typeunsigned int; it does not really matter, since both are actually referring to the same type.

Type aliases can be used to reduce the length of long or confusing type names, but they are most useful as tools to abstract programs from the underlying types they use. For example, by using an alias ofintto refer to a particular kind of parameter instead of usingintdirectly, it allows for the type to be easily replaced bylong(or some other type) in a later version, without having to change every instance where it is used.

UnionsUnions allow one portion of memory to be accessed as different data types. Its declaration and use is similar to the one of structures, but its functionality is totally different:union type_name { member_type1 member_name1; member_type2 member_name2; member_type3 member_name3; . .} object_names;

This creates a new union type, identified bytype_name, in which all its member elements occupy the same physical space in memory. The size of this type is the one of the largest member element. For example:12345union mytypes_t { char c; int i; float f;} mytypes;

declares an object (mytypes) with three members:123mytypes.cmytypes.imytypes.f

Each of these members is of a different data type. But since all of them are referring to the same location in memory, the modification of one of the members will affect the value of all of them. It is not possible to store different values in them in a way that each is independent of the others.

One of the uses of a union is to be able to access a value either in its entirety or as an array or structure of smaller elements. For example:12345678union mix_t { int l; struct { short hi; short lo; } s; char c[4];} mix;

If we assume that the system where this program runs has aninttype with a size of 4 bytes, and ashorttype of 2 bytes, the union defined above allows the access to the same group of 4 bytes:mix.l,mix.sandmix.c, and which we can use according to how we want to access these bytes: as if they were a single value of typeint, or as if they were two values of typeshort, or as an array ofcharelements, respectively. The example mixes types, arrays, and structures in the union to demonstrate different ways to access the data. For a little-endian system, this union could be represented as:

The exact alignment and order of the members of a union in memory depends on the system, with the possibility of creating portability issues.

Anonymous unionsWhen unions are members of a class (or structure), they can be declared with no name. In this case, they becomeanonymous unions, and its members are directly accessible from objects by their member names. For example, see the differences between these two structure declarations:structure with regular unionstructure with anonymous union

struct book1_t { char title[50]; char author[50]; union { float dollars; int yen; } price;} book1;struct book2_t { char title[50]; char author[50]; union { float dollars; int yen; };} book2;

The only difference between the two types is that in the first one, the member union has a name (price), while in the second it has not. This affects the way to access membersdollarsandyenof an object of this type. For an object of the first type (with a regular union), it would be:12book1.price.dollarsbook1.price.yen

whereas for an object of the second type (which has an anonymous union), it would be:12book2.dollarsbook2.yen

Again, remember that because it is a member union (not a member structure), the membersdollarsandyenactually share the same memory location, so they cannot be used to store two different values simultaneously. Thepricecan be set indollarsor inyen, but not in both simultaneously.

Enumerated types (enum)Enumerated typesare types that are defined with a set of custom identifiers, known asenumerators, as possible values. Objects of theseenumerated typescan take any of these enumerators as value.

Their syntax is:enum type_name { value1, value2, value3, . .} object_names;

This creates the typetype_name, which can take any ofvalue1,value2,value3, ... as value. Objects (variables) of this type can directly be instantiated asobject_names.

For example, a new type of variable calledcolors_tcould be defined to store colors with the following declaration:enum colors_t {black, blue, green, cyan, red, purple, yellow, white};

Notice that this declaration includes no other type, neither fundamental nor compound, in its definition. To say it another way, somehow, this creates a whole new data type from scratch without basing it on any other existing type. The possible values that variables of this new typecolor_tmay take are the enumerators listed within braces. For example, once thecolors_tenumerated type is declared, the following expressions will be valid:1234colors_t mycolor; mycolor = blue;if (mycolor == green) mycolor = red;

Values ofenumerated typesdeclared withenumare implicitly convertible to the integer typeint, and vice versa. In fact, the elements of such anenumare always assigned an integer numerical equivalent internally, of which they become an alias. If it is not specified otherwise, the integer value equivalent to the first possible value is0, the equivalent to the second is1, to the third is2, and so on... Therefore, in the data typecolors_tdefined above,blackwould be equivalent to0,bluewould be equivalent to1,greento2, and so on...

A specific integer value can be specified for any of the possible values in the enumerated type. And if the constant value that follows it is itself not given its own value, it is automatically assumed to be the same value plus one. For example:123enum months_t { january=1, february, march, april, may, june, july, august, september, october, november, december} y2k;

In this case, the variabley2kof the enumerated typemonths_tcan contain any of the 12 possible values that go fromjanuarytodecemberand that are equivalent to the values between1and12(not between0and11, sincejanuaryhas been made equal to1).

Because enumerated types declared withenumare implicitly convertible toint, and each of the enumerator values is actually of typeint, there is no way to distinguish1fromjanuary- they are the exact same value of the same type. The reasons for this are historical and are inheritance of the C language.

Enumerated types with enum classBut, in C++, it is possible to create realenumtypes that are neither implicitly convertible tointand that neither have enumerator values of typeint, but of theenumtype itself, thus preserving type safety. They are declared withenum class(orenum struct) instead of justenum:enum class Colors {black, blue, green, cyan, red, purple, yellow, white};

Each of the enumerator values of anenum classtype needs to be scoped into its type (this is actually also possible withenumtypes, but it is only optional). For example:1234Colors mycolor; mycolor = Colors::blue;if (mycolor == Colors::green) mycolor = Colors::red;

Enumerated types declared withenum classalso have more control over their underlying type; it may be any integral data type, such aschar,shortorunsigned int, which essentially serves to determine the size of the type. This is specified by a colon and the underlying type following the enumerated type. For example:enum class EyeColor : char {blue, green, brown};

Here,Eyecoloris a distinct type with the same size of achar(1 byte).

119