UNIT 1
Introduction to C++
The major purpose of C++ programming is to introduce the concept of object orientation to the C programming language.
Object Oriented Programming is a paradigm that provides many concepts such as inheritance, data binding, polymorphism etc.
The programming paradigm where everything is represented as an object is known as truly object-oriented programming language. Smalltalk is considered as the first truly object-oriented programming language.
OOPs (Object Oriented Programming System)
Object means a real word entity such as pen, chair, table etc. Object-Oriented Programming is a methodology or paradigm to design a program using classes and objects. It simplifies the software development and maintenance by providing some concepts:
- Object
- Class
- Inheritance
- Polymorphism
- Abstraction
- Encapsulation
Object
Any entity that has state and behavior is known as an object. For example: chair, pen, table, keyboard, bike etc. It can be physical and logical.
Class
Collection of objects is called class. It is a logical entity.
Inheritance
When one object acquires all the properties and behaviours of parent object i.e. known as inheritance. It provides code reusability. It is used to achieve runtime polymorphism.
Polymorphism
When one task is performed by different ways i.e. known as polymorphism. For example: to convince the customer differently, to draw something e.g. Shape or rectangle etc.
In C++, we use Function overloading and Function overriding to achieve polymorphism.
Abstraction
Hiding internal details and showing functionality is known as abstraction. For example: phone call, we don't know the internal processing.
In C++, we use abstract class and interface to achieve abstraction.
Encapsulation
Binding (or wrapping) code and data together into a single unit is known as encapsulation. For example: capsule, it is wrapped with different medicines.
Advantage of OOPs over Procedure-oriented programming language
- OOPs makes development and maintenance easier where as in Procedure-oriented programming language it is not easy to manage if code grows as project size grows.
- OOPs provide data hiding whereas in Procedure-oriented programming language a global data can be accessed from anywhere.
- OOPs provide ability to simulate real-world event much more effectively. We can provide the solution of real word problem if we are using the Object-Oriented Programming language.
The C++ standard libraries provide an extensive set of input/output capabilities which we will see in subsequent chapters. This chapter will discuss very basic and most common I/O operations required for C++ programming.
C++ I/O occurs in streams, which are sequences of bytes. If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main memory, this is called input operation and if bytes flow from main memory to a device like a display screen, a printer, a disk drive, or a network connection, etc., this is called output operation.
I/O Library Header Files
There are following header files important to C++ programs −
Sr.No | Header File & Function and Description |
1 | <iostream> This file defines the cin, cout, cerr and clog objects, which correspond to the standard input stream, the standard output stream, the un-buffered standard error stream and the buffered standard error stream, respectively. |
2 | <iomanip> This file declares services useful for performing formatted I/O with so-called parameterized stream manipulators, such as setw and setprecision. |
3 | <fstream> This file declares services for user-controlled file processing. We will discuss about it in detail in File and Stream related chapter. |
The Standard Output Stream (cout)
The predefined object cout is an instance of ostream class. The cout object is said to be "connected to" the standard output device, which usually is the display screen. The cout is used in conjunction with the stream insertion operator, which is written as << which are two less than signs as shown in the following example.
#include <iostream>
Using namespace std;
Int main() {
Char str[] = "Hello C++";
Cout << "Value of str is : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Value of str is : Hello C++
The C++ compiler also determines the data type of variable to be output and selects the appropriate stream insertion operator to display the value. The << operator is overloaded to output data items of built-in types integer, float, double, strings and pointer values.
The insertion operator << may be used more than once in a single statement as shown above and endl is used to add a new-line at the end of the line.
The Standard Input Stream (cin)
The predefined object cin is an instance of istream class. The cin object is said to be attached to the standard input device, which usually is the keyboard. The cin is used in conjunction with the stream extraction operator, which is written as >> which are two greater than signs as shown in the following example.
#include <iostream>
Using namespace std;
Int main() {
Char name[50];
Cout << "Please enter your name: ";
Cin >> name;
Cout << "Your name is: " << name << endl;
}
When the above code is compiled and executed, it will prompt you to enter a name. You enter a value and then hit enter to see the following result −
Please enter your name: cplusplus
Your name is: cplusplus
The C++ compiler also determines the data type of the entered value and selects the appropriate stream extraction operator to extract the value and store it in the given variables.
The stream extraction operator >> may be used more than once in a single statement. To request more than one datum you can use the following −
Cin >> name >> age;
This will be equivalent to the following two statements −
Cin >> name;
Cin >> age;
The Standard Error Stream (cerr)
The predefined object cerr is an instance of ostream class. The cerr object is said to be attached to the standard error device, which is also a display screen but the object cerr is un-buffered and each stream insertion to cerr causes its output to appear immediately.
The cerr is also used in conjunction with the stream insertion operator as shown in the following example.
#include <iostream>
Using namespace std;
Int main() {
Char str[] = "Unable to read....";
Cerr << "Error message : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Error message : Unable to read....
The Standard Log Stream (clog)
The predefined object clog is an instance of ostream class. The clog object is said to be attached to the standard error device, which is also a display screen but the object clog is buffered. This means that each insertion to clog could cause its output to be held in a buffer until the buffer is filled or until the buffer is flushed.
The clog is also used in conjunction with the stream insertion operator as shown in the following example.
#include <iostream>
Using namespace std;
Int main() {
Char str[] = "Unable to read....";
Clog << "Error message : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Error message : Unable to read....
You would not be able to see any difference in cout, cerr and clog with these small examples, but while writing and executing big programs the difference becomes obvious. So it is good practice to display error messages using cerr stream and while displaying other log messages then clog should be used.
What is Token in C?
TOKEN is the smallest unit in a 'C' program. It is each and every word and punctuation that you come across in your C program. The compiler breaks a program into the smallest possible units (tokens) and proceeds to the various stages of the compilation. A token is divided into six different types, viz, Keywords, Operators, Strings, Constants, Special Characters, and Identifiers.
In 'C' every word can be either a keyword or an identifier.
Keywords have fixed meanings, and the meaning cannot be changed. They act as a building block of a 'C' program. There are a total of 32 keywords in 'C'. Keywords are written in lowercase letters.
Following table represents the keywords in 'C'-
Auto | Double | Int | Struct |
Break | Else | Long | Switch |
Case | Enum | Register | Typedef |
Char | Extern | Return | Union |
Const | Short | Float | Unsigned |
Continue | For | Signed | Void |
Default | Goto | Sizeof | Volatile |
Do | If | Static | While |
An identifier is nothing but a name assigned to an element in a program. Example, name of a variable, function, etc. Identifiers are the user-defined names consisting of 'C' standard character set. As the name says, identifiers are used to identify a particular element in a program. Each identifier must have a unique name. Following rules must be followed for identifiers:
- The first character must always be an alphabet or an underscore.
- It should be formed using only letters, numbers, or underscore.
- A keyword cannot be used as an identifier.
- It should not contain any whitespace character.
- The name must be meaningful.
Summary
- A token is the smallest unit in a program.
- A keyword is reserved words by language.
- There are total of 32 keywords.
- An identifier is used to identify elements of a program.
Data types
'C++' provides various data types to make it easy for a programmer to select a suitable data type as per the requirements of an application. Following are the three data types:
- Primitive data types
- Derived data types
- User-defined data types
There are five primary fundamental data types,
- Int for integer data
- Char for character data
- Float for floating point numbers
- Double for double precision floating point numbers
- Void
Array, functions, pointers, structures are derived data types. 'C' language provides more extended versions of the above mentioned primary data types. Each data type differs from one another in size and range. Following table displays the size and range of each data type.
Data type | Size in bytes | Range |
Char or signed char | 1 | -128 to 127 |
Unsigned char | 1 | 0 to 255 |
Int or signed int | 2 | -32768 to 32767 |
Unsigned int | 2 | 0 to 65535 |
Short int or Unsigned short int | 2 | 0 to 255 |
Signed short int | 2 | -128 to 127 |
Long int or Signed long int | 4 | -2147483648 to 2147483647 |
Unsigned long int | 4 | 0 to 4294967295 |
Float | 4 | 3.4E-38 to 3.4E+38 |
Double | 8 | 1.7E-308 to 1.7E+308 |
Long double | 10 | 3.4E-4932 to 1.1E+4932 |
Note: In C, there is no Boolean data type.
Integer data type
Integer is nothing but a whole number. The range for an integer data type varies from machine to machine. The standard range for an integer data type is -32768 to 32767.
An integer typically is of 2 bytes which means it consumes a total of 16 bits in memory. A single integer value takes 2 bytes of memory. An integer data type is further divided into other data types such as short int, int, and long int.
Each data type differs in range even though it belongs to the integer data type family. The size may not change for each data type of integer family.
The short int is mostly used for storing small numbers, int is used for storing averagely sized integer values, and long int is used for storing large integer values.
Whenever we want to use an integer data type, we have place int before the identifier such as,
Int age;
Here, age is a variable of an integer data type which can be used to store integer values.
Floating point data type
Like integers, in 'C' program we can also make use of floating point data types. The 'float' keyword is used to represent the floating point data type. It can hold a floating point value which means a number is having a fraction and a decimal part. A floating point value is a real number that contains a decimal point. Integer data type doesn't store the decimal part hence we can use floats to store decimal part of a value.
Generally, a float can hold up to 6 precision values. If the float is not sufficient, then we can make use of other data types that can hold large floating point values. The data type double and long double are used to store real numbers with precision up to 14 and 80 bits respectively.
While using a floating point number a keyword float/double/long double must be placed before an identifier. The valid examples are,
Float division;
Double BankBalance;
Character data type
Character data types are used to store a single character value enclosed in single quotes.
A character data type takes up-to 1 byte of memory space.
Example,
Char letter;
Void data type
A void data type doesn't contain or return any value. It is mostly used for defining functions in 'C'.
Example,
Void displayData()
Type declaration of a variable
Int main() {
Int x, y;
Float salary = 13.48;
Char letter = 'K';
x = 25;
y = 34;
Int z = x+y;
Printf("%d \n", z);
Printf("%f \n", salary);
Printf("%c \n", letter);
Return 0;}
Output:
59
13.480000
K
We can declare multiple variables with the same data type on a single line by separating them with a comma. Also, notice the use of format specifiers in printf output function float (%f) and char (%c) and int (%d).
The data-types that are derived from the primitive or built-in datatypes are referred to as Derived Data Types. These can be of four types namely:
- Function
- Array
- Pointers
- References
Let’s briefly understand each of the following derived datatypes:
- Function: A function is a block of code or program-segment that is defined to perform a specific well-defined task. A function is generally defined to save the user from writing the same lines of code again and again for the same input. All the lines of code are put together inside a single function and this can be called anywhere required. Main() is a default function that is defined in every program of C++.
Syntax:
FunctionType FunctionName(parameters)
Example:
// C++ program to demonstrate // Function Derived Type
#include <iostream> Using namespace std;
// max here is a function derived type Int max(int x, int y) { If (x > y) Return x; Else Return y; }
// main is the default function derived type Int main() { Int a = 10, b = 20;
// Calling above function to // find max of 'a' and 'b' Int m = max(a, b);
Cout << "m is " << m; Return 0; } |
Output:
m is 20
2. Array: An array is a collection of items stored at continuous memory locations. The idea of array is to represent many instances in one variable.
Syntax:
DataType ArrayName[size_of_array];
Example:
// C++ program to demonstrate // Array Derived Type
#include <iostream> Using namespace std; Int main() {
// Array Derived Type Int arr[5]; Arr[0] = 5; Arr[2] = -10;
// this is same as arr[1] = 2 Arr[3 / 2] = 2;
Arr[3] = arr[0];
Cout<<arr[0]<<" "<<arr[1]<<" "<<arr[2]<<" "<<arr[3];
Return 0; } |
Output:
5 2 -10 5
3. Pointers: Pointers are symbolic representation of addresses. They enable programs to simulate call-by-reference as well as to create and manipulate dynamic data structures. It’s general declaration in C/C++ has the format:
Syntax:
Datatype *var_name;
Example:
Int *ptr;
Ptr points to an address
Which holds int data
Example:
// C++ program to illustrate // Pointers Derived Type
#include <bits/stdc++.h> Using namespace std;
Void geeks() { Int var = 20;
// Pointers Derived Type // declare pointer variable Int* ptr;
// note that data type of ptr // and var must be same Ptr = &var;
// assign the address of a variable // to a pointer Cout << "Value at ptr = " << ptr << "\n"; Cout << "Value at var = " << var << "\n"; Cout << "Value at *ptr = " << *ptr << "\n"; }
// Driver program Int main() { Geeks(); } |
Output:
Value at ptr = 0x7ffc10d7fd5c
Value at var = 20
Value at *ptr = 20
4. Reference: When a variable is declared as reference, it becomes an alternative name for an existing variable. A variable can be declared as reference by putting ‘&’ in the declaration.
Example:
// C++ program to illustrate // Reference Derived Type
#include <iostream> Using namespace std;
Int main() { Int x = 10;
// Reference Derived Type // ref is a reference to x. Int& ref = x;
// Value of x is now changed to 20 Ref = 20; Cout << "x = " << x << endl;
// Value of x is now changed to 30 x = 30; Cout << "ref = " << ref << endl;
Return 0; } |
Output:
x = 20
Ref = 30
The void data type, similar to the Nothing data type described earlier, is the data type for the result of a function that returns normally, but does not provide a result value to its caller.
Discussion
The void data type has no values and no operations. It’s a data type that represents the lack of a data type.
Language | Reserved Word |
C++ | Void |
C# | Void |
Java | Void |
JavaScript | Void |
Python | N/A |
Swift | Void |
Many programming languages need a data type to define the lack of return value to indicate that nothing is being returned. The void data type is typically used in the definition and prototyping of functions to indicate that either nothing is being passed in and/or nothing is being returned.
Key Terms
Void data type
A data type that has no values or operators and is used to represent nothing.
C++ allows the char, int, and double data types to have modifiers preceding them. A modifier is used to alter the meaning of the base type so that it more precisely fits the needs of various situations.
The data type modifiers are listed here −
- Signed
- Unsigned
- Long
- Short
The modifiers signed, unsigned, long, and short can be applied to integer base types. In addition, signed and unsigned can be applied to char, and long can be applied to double.
The modifiers signed and unsigned can also be used as prefix to long or short modifiers. For example, unsigned long int.
C++ allows a shorthand notation for declaring unsigned, short, or long integers. You can simply use the word unsigned, short, or long, without int. It automatically implies int. For example, the following two statements both declare unsigned integer variables.
Unsigned x;
Unsigned int y;
To understand the difference between the way signed and unsigned integer modifiers are interpreted by C++, you should run the following short program −
#include <iostream>
Using namespace std;
/* This program shows the difference between
* signed and unsigned integers.
*/
Int main() {
Short int i; // a signed short integer
Short unsigned int j; // an unsigned short integer
j = 50000;
i = j;
Cout << i << " " << j;
Return 0;
}
When this program is run, following is the output −
-15536 50000
The above result is because the bit pattern that represents 50,000 as a short unsigned integer is interpreted as -15,536 by a short.
Type Qualifiers in C++
The type qualifiers provide additional information about the variables they precede.
Sr.No | Qualifier & Meaning |
1 | Const Objects of type const cannot be changed by your program during execution. |
2 | Volatile The modifier volatile tells the compiler that a variable's value may be changed in ways not explicitly specified by the program. |
3 | Restrict A pointer qualified by restrict is initially the only means by which the object it points to can be accessed. Only C99 adds a new type qualifier called restrict. |
Converting an expression of a given type into another type is known as type-casting. We have already seen some ways to type cast:
Implicit conversion
Implicit conversions do not require any operator. They are automatically performed when a value is copied to a compatible type. For example:
1 | Short a=2000; Int b; b=a; |
|
Here, the value of a has been promoted from short to int and we have not had to specify any type-casting operator. This is known as a standard conversion. Standard conversions affect fundamental data types, and allow conversions such as the conversions between numerical types (short to int, int to float, double to int...), to or from bool, and some pointer conversions. Some of these conversions may imply a loss of precision, which the compiler can signal with a warning. This warning can be avoided with an explicit conversion.
Implicit conversions also include constructor or operator conversions, which affect classes that include specific constructors or operator functions to perform conversions. For example:
1 | Class A {}; Class B { public: B (A a) {} };
A a; B b=a; |
|
Here, an implicit conversion happened between objects of class A and class B, because B has a constructor that takes an object of class A as parameter. Therefore implicit conversions from A to B are allowed.
Explicit conversion
C++ is a strong-typed language. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion. We have already seen two notations for explicit type conversion: functional and c-like casting:
1 | Short a=2000; Int b; b = (int) a; // c-like cast notation b = int (a); // functional notation |
|
The functionality of these explicit conversion operators is enough for most needs with fundamental data types. However, these operators can be applied indiscriminately on classes and pointers to classes, which can lead to code that while being syntactically correct can cause runtime errors. For example, the following code is syntactically correct:
1 | // class type-casting #include <iostream> Using namespace std;
Class CDummy { Float i,j; };
Class CAddition { Int x,y; Public: CAddition (int a, int b) { x=a; y=b; } Int result() { return x+y;} };
Int main () { CDummy d; CAddition * padd; Padd = (CAddition*) &d; Cout << padd->result(); Return 0; } |
|
|
The program declares a pointer to CAddition, but then it assigns to it a reference to an object of another incompatible type using explicit type-casting:
| Padd = (CAddition*) &d; |
|
Traditional explicit type-casting allows to convert any pointer into any other pointer type, independently of the types they point to. The subsequent call to member result will produce either a run-time error or a unexpected result.
In order to control these types of conversions between classes, we have four specific casting operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new_type) expression
new_type (expression)
but each one with its own special characteristics:
Dynamic_cast
dynamic_cast can be used only with pointers and references to objects. Its purpose is to ensure that the result of the type conversion is a valid complete object of the requested class.
Therefore, dynamic_cast is always successful when we cast a class to one of its base classes:
1 | Class CBase { }; Class CDerived: public CBase { };
CBase b; CBase* pb; CDerived d; CDerived* pd;
Pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base Pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived |
|
The second conversion in this piece of code would produce a compilation error since base-to-derived conversions are not allowed with dynamic_cast unless the base class is polymorphic.
When a class is polymorphic, dynamic_cast performs a special checking during runtime to ensure that the expression yields a valid complete object of the requested class:
1 | // dynamic_cast #include <iostream> #include <exception> Using namespace std;
Class CBase { virtual void dummy() {} }; Class CDerived: public CBase { int a; };
Int main () { Try { CBase * pba = new CDerived; CBase * pbb = new CBase; CDerived * pd;
Pd = dynamic_cast<CDerived*>(pba); If (pd==0) cout << "Null pointer on first type-cast" << endl;
Pd = dynamic_cast<CDerived*>(pbb); If (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();} Return 0; } | Null pointer on second type-cast |
|
Compatibility note: dynamic_cast requires the Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This must be enabled for runtime type checking using dynamic_cast to work properly. |
The code tries to perform two dynamic casts from pointer objects of type CBase* (pba and pbb) to a pointer object of type CDerived*, but only the first one is successful. Notice their respective initializations:
1 | CBase * pba = new CDerived; CBase * pbb = new CBase; |
|
Even though both are pointers of type CBase*, pba points to an object of type CDerived, while pbb points to an object of type CBase. Thus, when their respective type-castings are performed using dynamic_cast, pba is pointing to a full object of class CDerived, whereas pbb is pointing to an object of class CBase, which is an incomplete object of class CDerived.
When dynamic_cast cannot cast a pointer because it is not a complete object of the required class -as in the second conversion in the previous example- it returns a null pointer to indicate the failure. If dynamic_cast is used to convert to a reference type and the conversion is not possible, an exception of type bad_cast is thrown instead.
dynamic_cast can also cast null pointers even between pointers to unrelated classes, and can also cast pointers of any type to void pointers (void*).
Static_cast
Static_cast can perform conversions between pointers to related classes, not only from the derived class to its base, but also from a base class to its derived. This ensures that at least the classes are compatible if the proper object is converted, but no safety check is performed during runtime to check if the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, the overhead of the type-safety checks of dynamic_cast is avoided.
1 | Class CBase {}; Class CDerived: public CBase {}; CBase * a = new CBase; CDerived * b = static_cast<CDerived*>(a); |
|
This would be valid, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.
static_cast can also be used to perform any other non-pointer conversion that could also be performed implicitly, like for example standard conversion between fundamental types:
1 | Double d=3.14159265; Int i = static_cast<int>(d); |
|
Or any conversion between classes with explicit constructors or operator functions as described in "implicit conversions" above.
Reinterpret_cast
Reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.
It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it, is granted to be able to be cast back to a valid pointer.
The conversions that can be performed by reinterpret_cast but not by static_cast are low-level operations, whose interpretation results in code which is generally system-specific, and thus non-portable. For example:
1 | Class A {}; Class B {}; A * a = new A; B * b = reinterpret_cast<B*>(a); |
|
This is valid C++ code, although it does not make much sense, since now we have a pointer that points to an object of an incompatible class, and thus dereferencing it is unsafe.
Const_cast
This type of casting manipulates the constness of an object, either to be set or to be removed. For example, in order to pass a const argument to a function that expects a non-constant parameter:
1 | // const_cast #include <iostream> Using namespace std;
Void print (char * str) { Cout << str << endl; }
Int main () { Const char * c = "sample text"; Print ( const_cast<char *> (c) ); Return 0; } | Sample text |
|
Typeid
Typeid allows to check the type of an expression:
typeid (expression)
This operator returns a reference to a constant object of type type_info that is defined in the standard header file <typeinfo>. This returned value can be compared with another one using operators == and != or can serve to obtain a null-terminated character sequence representing the data type or class name by using its name() member.
1 | // typeid #include <iostream> #include <typeinfo> Using namespace std;
Int main () { Int * a,b; a=0; b=0; If (typeid(a) != typeid(b)) { Cout << "a and b are of different types:\n"; Cout << "a is: " << typeid(a).name() << '\n'; Cout << "b is: " << typeid(b).name() << '\n'; } Return 0; } | a and b are of different types: a is: int * b is: int |
|
When typeid is applied to classes typeid uses the RTTI to keep track of the type of dynamic objects. When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:
1 | // typeid, polymorphic class #include <iostream> #include <typeinfo> #include <exception> Using namespace std;
Class CBase { virtual void f(){} }; Class CDerived : public CBase {};
Int main () { Try { CBase* a = new CBase; CBase* b = new CDerived; Cout << "a is: " << typeid(a).name() << '\n'; Cout << "b is: " << typeid(b).name() << '\n'; Cout << "*a is: " << typeid(*a).name() << '\n'; Cout << "*b is: " << typeid(*b).name() << '\n'; } catch (exception& e) { cout << "Exception: " << e.what() << endl; } Return 0; } | a is: class CBase * b is: class CBase * *a is: class CBase *b is: class CDerived |
|
Note: The string returned by member name of type_info depends on the specific implementation of your compiler and library. It is not necessarily a simple string with its typical type name, like in the compiler used to produce this output.
Notice how the type that typeid considers for pointers is the pointer type itself (both a and b are of type class CBase *). However, when typeid is applied to objects (like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object).
If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.
The compiler in the examples above generates names with type_info::name that are easily readable by users, but this is not a requirement: a compiler may just return any string.
Constants refer to fixed values that the program may not alter and they are called literals.
Constants can be of any of the basic data types and can be divided into Integer Numerals, Floating-Point Numerals, Characters, Strings and Boolean Values.
Again, constants are treated just like regular variables except that their values cannot be modified after their definition.
Integer Literals
An integer literal can be a decimal, octal, or hexadecimal constant. A prefix specifies the base or radix: 0x or 0X for hexadecimal, 0 for octal, and nothing for decimal.
An integer literal can also have a suffix that is a combination of U and L, for unsigned and long, respectively. The suffix can be uppercase or lowercase and can be in any order.
Here are some examples of integer literals −
212 // Legal
215u // Legal
0xFeeL // Legal
078 // Illegal: 8 is not an octal digit
032UU // Illegal: cannot repeat a suffix
Following are other examples of various types of Integer literals −
85 // decimal
0213 // octal
0x4b // hexadecimal
30 // int
30u // unsigned int
30l // long
30ul // unsigned long
Floating-point Literals
A floating-point literal has an integer part, a decimal point, a fractional part, and an exponent part. You can represent floating point literals either in decimal form or exponential form.
While representing using decimal form, you must include the decimal point, the exponent, or both and while representing using exponential form, you must include the integer part, the fractional part, or both. The signed exponent is introduced by e or E.
Here are some examples of floating-point literals −
3.14159 // Legal
314159E-5L // Legal
510E // Illegal: incomplete exponent
210f // Illegal: no decimal or exponent
.e55 // Illegal: missing integer or fraction
Boolean Literals
There are two Boolean literals and they are part of standard C++ keywords −
- A value of true representing true.
- A value of false representing false.
You should not consider the value of true equal to 1 and value of false equal to 0.
Character Literals
Character literals are enclosed in single quotes. If the literal begins with L (uppercase only), it is a wide character literal (e.g., L'x') and should be stored in wchar_t type of variable . Otherwise, it is a narrow character literal (e.g., 'x') and can be stored in a simple variable of char type.
A character literal can be a plain character (e.g., 'x'), an escape sequence (e.g., '\t'), or a universal character (e.g., '\u02C0').
There are certain characters in C++ when they are preceded by a backslash they will have special meaning and they are used to represent like newline (\n) or tab (\t). Here, you have a list of some of such escape sequence codes −
Escape sequence | Meaning |
\\ | \ character |
\' | ' character |
\" | " character |
\? | ? character |
\a | Alert or bell |
\b | Backspace |
\f | Form feed |
\n | Newline |
\r | Carriage return |
\t | Horizontal tab |
\v | Vertical tab |
\ooo | Octal number of one to three digits |
\xhh . . . | Hexadecimal number of one or more digits |
Following is the example to show a few escape sequence characters −
#include <iostream>
Using namespace std;
Int main() {
Cout << "Hello\tWorld\n\n";
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Hello World
String Literals
String literals are enclosed in double quotes. A string contains characters that are similar to character literals: plain characters, escape sequences, and universal characters.
You can break a long line into multiple lines using string literals and separate them using whitespaces.
Here are some examples of string literals. All the three forms are identical strings.
"hello, dear"
"hello, \
Dear"
"hello, " "d" "ear"
Defining Constants
There are two simple ways in C++ to define constants −
- Using #define preprocessor.
- Using const keyword.
The #define Preprocessor
Following is the form to use #define preprocessor to define a constant −
#define identifier value
Following example explains it in detail −
#include <iostream>
Using namespace std;
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
Int main() {
Int area;
Area = LENGTH * WIDTH;
Cout << area;
Cout << NEWLINE;
Return 0;
}
When the above code is compiled and executed, it produces the following result −
50
The const Keyword
You can use const prefix to declare constants with a specific type as follows −
Const type variable = value;
Following example explains it in detail −
#include <iostream>
Using namespace std;
Int main() {
Const int LENGTH = 10;
Const int WIDTH = 5;
Const char NEWLINE = '\n';
Int area;
Area = LENGTH * WIDTH;
Cout << area;
Cout << NEWLINE;
Return 0;
}
When the above code is compiled and executed, it produces the following result −
50
Note that it is a good programming practice to define constants in CAPITALS.
An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. C++ is rich in built-in operators and provide the following types of operators −
- Arithmetic Operators
- Relational Operators
- Logical Operators
- Bitwise Operators
- Assignment Operators
- Misc Operators
This chapter will examine the arithmetic, relational, logical, bitwise, assignment and other operators one by one.
Arithmetic Operators
There are following arithmetic operators supported by C++ language −
Assume variable A holds 10 and variable B holds 20, then −
Show Examples
Operator | Description | Example |
+ | Adds two operands | A + B will give 30 |
- | Subtracts second operand from the first | A - B will give -10 |
* | Multiplies both operands | A * B will give 200 |
/ | Divides numerator by de-numerator | B / A will give 2 |
% | Modulus Operator and remainder of after an integer division | B % A will give 0 |
++ | Increment operator, increases integer value by one | A++ will give 11 |
-- | Decrement operator, decreases integer value by one | A-- will give 9 |
Relational Operators
There are following relational operators supported by C++ language
Assume variable A holds 10 and variable B holds 20, then −
Show Examples
Operator | Description | Example |
== | Checks if the values of two operands are equal or not, if yes then condition becomes true. | (A == B) is not true. |
!= | Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. | (A != B) is true. |
> | Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. | (A > B) is not true. |
< | Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. | (A < B) is true. |
>= | Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. | (A >= B) is not true. |
<= | Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. | (A <= B) is true. |
Logical Operators
There are following logical operators supported by C++ language.
Assume variable A holds 1 and variable B holds 0, then −
Show Examples
Operator | Description | Example |
&& | Called Logical AND operator. If both the operands are non-zero, then condition becomes true. | (A && B) is false. |
|| | Called Logical OR Operator. If any of the two operands is non-zero, then condition becomes true. | (A || B) is true. |
! | Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then Logical NOT operator will make false. | !(A && B) is true. |
Bitwise Operators
Bitwise operator works on bits and perform bit-by-bit operation. The truth tables for &, |, and ^ are as follows −
p | q | p & q | p | q | p ^ q |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Assume if A = 60; and B = 13; now in binary format they will be as follows −
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
The Bitwise operators supported by C++ language are listed in the following table. Assume variable A holds 60 and variable B holds 13, then −
Show Examples
Operator | Description | Example |
& | Binary AND Operator copies a bit to the result if it exists in both operands. | (A & B) will give 12 which is 0000 1100 |
| | Binary OR Operator copies a bit if it exists in either operand. | (A | B) will give 61 which is 0011 1101 |
^ | Binary XOR Operator copies the bit if it is set in one operand but not both. | (A ^ B) will give 49 which is 0011 0001 |
~ | Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. | (~A ) will give -61 which is 1100 0011 in 2's complement form due to a signed binary number. |
<< | Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. | A << 2 will give 240 which is 1111 0000 |
>> | Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. | A >> 2 will give 15 which is 0000 1111 |
Assignment Operators
There are following assignment operators supported by C++ language −
Show Examples
Operator | Description | Example |
= | Simple assignment operator, Assigns values from right side operands to left side operand. | C = A + B will assign value of A + B into C |
+= | Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand. | C += A is equivalent to C = C + A |
-= | Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand. | C -= A is equivalent to C = C - A |
*= | Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand. | C *= A is equivalent to C = C * A |
/= | Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand. | C /= A is equivalent to C = C / A |
%= | Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand. | C %= A is equivalent to C = C % A |
<<= | Left shift AND assignment operator. | C <<= 2 is same as C = C << 2 |
>>= | Right shift AND assignment operator. | C >>= 2 is same as C = C >> 2 |
&= | Bitwise AND assignment operator. | C &= 2 is same as C = C & 2 |
^= | Bitwise exclusive OR and assignment operator. | C ^= 2 is same as C = C ^ 2 |
|= | Bitwise inclusive OR and assignment operator. | C |= 2 is same as C = C | 2 |
Misc Operators
The following table lists some other operators that C++ supports.
Sr.No | Operator & Description |
1 | Sizeof Sizeof operator returns the size of a variable. For example, sizeof(a), where ‘a’ is integer, and will return 4. |
2 | Condition ? X : Y Conditional operator (?). If Condition is true then it returns value of X otherwise returns value of Y. |
3 | , Comma operator causes a sequence of operations to be performed. The value of the entire comma expression is the value of the last expression of the comma-separated list. |
4 | . (dot) and -> (arrow) Member operators are used to reference individual members of classes, structures, and unions. |
5 | Cast Casting operators convert one data type to another. For example, int(2.2000) would return 2. |
6 | & Pointer operator & returns the address of a variable. For example &a; will give actual address of the variable. |
7 | * Pointer operator * is pointer to a variable. For example *var; will pointer to a variable var. |
Operators Precedence in C++
Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator −
For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.
Show Examples
Category | Operator | Associativity |
Postfix | () [] -> . ++ - - | Left to right |
Unary | + - ! ~ ++ - - (type)* & sizeof | Right to left |
Multiplicative | * / % | Left to right |
Additive | + - | Left to right |
Shift | << >> | Left to right |
Relational | < <= > >= | Left to right |
Equality | == != | Left to right |
Bitwise AND | & | Left to right |
Bitwise XOR | ^ | Left to right |
Bitwise OR | | | Left to right |
Logical AND | && | Left to right |
Logical OR | || | Left to right |
Conditional | ?: | Right to left |
Assignment | = += -= *= /= %=>>= <<= &= ^= |= | Right to left |
Comma | , | Left to right |
Operator precedence determines the grouping of terms in an expression. The associativity of an operator is a property that determines how operators of the same precedence are grouped in the absence of parentheses. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator:
For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.
Category | Operator | Associativity |
Postfix | () [] -> . ++ - - | Left to right |
Unary | + - ! ~ ++ - - (type)* & sizeof | Right to left |
Multiplicative | * / % | Left to right |
Additive | + - | Left to right |
Shift | << >> | Left to right |
Relational | < <= > >= | Left to right |
Equality | == != | Left to right |
Bitwise AND | & | Left to right |
Bitwise XOR | ^ | Left to right |
Bitwise OR | | | Left to right |
Logical AND | && | Left to right |
Logical OR | || | Left to right |
Conditional | ?: | Right to left |
Assignment | = += -= *= /= %=>>= <<= &= ^= |= | Right to left |
Comma | , | Left to right |
In C++, string is an object of std::string class that represents sequence of characters. We can perform many operations on strings such as concatenation, comparison, conversion etc.
C++ String Example
Let's see the simple example of C++ string.
- #include <iostream>
- Using namespace std;
- Int main( ) {
- String s1 = "Hello";
- Char ch[] = { 'C', '+', '+'};
- String s2 = string(ch);
- Cout<<s1<<endl;
- Cout<<s2<<endl;
- }
Output:
Hello
C++
C++ String Compare Example
Let's see the simple example of string comparison using strcmp() function.
- #include <iostream>
- #include <cstring>
- Using namespace std;
- Int main ()
- {
- Char key[] = "mango";
- Char buffer[50];
- Do {
- Cout<<"What is my favourite fruit? ";
- Cin>>buffer;
- } while (strcmp (key,buffer) != 0);
- Cout<<"Answer is correct!!"<<endl;
- Return 0;
- }
Output:
What is my favourite fruit? apple
What is my favourite fruit? banana
What is my favourite fruit? mango
Answer is correct!!
C++ String Concat Example
Let's see the simple example of string concatenation using strcat() function.
- #include <iostream>
- #include <cstring>
- Using namespace std;
- Int main()
- {
- Char key[25], buffer[25];
- Cout << "Enter the key string: ";
- Cin.getline(key, 25);
- Cout << "Enter the buffer string: ";
- Cin.getline(buffer, 25);
- Strcat(key, buffer);
- Cout << "Key = " << key << endl;
- Cout << "Buffer = " << buffer<<endl;
- Return 0;
- }
Output:
Enter the key string: Welcome to
Enter the buffer string: C++ Programming.
Key = Welcome to C++ Programming.
Buffer = C++ Programming.
C++ String Copy Example
Let's see the simple example of copy the string using strcpy() function.
- #include <iostream>
- #include <cstring>
- Using namespace std;
- Int main()
- {
- Char key[25], buffer[25];
- Cout << "Enter the key string: ";
- Cin.getline(key, 25);
- Strcpy(buffer, key);
- Cout << "Key = "<< key << endl;
- Cout << "Buffer = "<< buffer<<endl;
- Return 0;
- }
Output:
Enter the key string: C++ Tutorial
Key = C++ Tutorial
Buffer = C++ Tutorial
C++ String Length Example
Let's see the simple example of finding the string length using strlen() function.
- #include <iostream>
- #include <cstring>
- Using namespace std;
- Int main()
- {
- Char ary[] = "Welcome to C++ Programming";
- Cout << "Length of String = " << strlen(ary)<<endl;
- Return 0;
- }
Output:
Length of String = 26
C++ String Functions
Function | Description |
Int compare(const string& str) | It is used to compare two string objects. |
Int length() | It is used to find the length of the string. |
Void swap(string& str) | It is used to swap the values of two string objects. |
String substr(int pos,int n) | It creates a new string object of n characters. |
Int size() | It returns the length of the string in terms of bytes. |
Void resize(int n) | It is used to resize the length of the string up to n characters. |
String& replace(int pos,int len,string& str) | It replaces portion of the string that begins at character position pos and spans len characters. |
String& append(const string& str) | It adds new characters at the end of another string object. |
Char& at(int pos) | It is used to access an individual character at specified position pos. |
Int find(string& str,int pos,int n) | It is used to find the string specified in the parameter. |
Int find_first_of(string& str,int pos,int n) | It is used to find the first occurrence of the specified sequence. |
Int find_first_not_of(string& str,int pos,int n ) | It is used to search the string for the first character that does not match with any of the characters specified in the string. |
Int find_last_of(string& str,int pos,int n) | It is used to search the string for the last character of specified sequence. |
Int find_last_not_of(string& str,int pos) | It searches for the last character that does not match with the specified sequence. |
String& insert() | It inserts a new character before the character indicated by the position pos. |
Int max_size() | It finds the maximum length of the string. |
Void push_back(char ch) | It adds a new character ch at the end of the string. |
Void pop_back() | It removes a last character of the string. |
String& assign() | It assigns new value to the string. |
Int copy(string& str) | It copies the contents of string into another. |
Char& back() | It returns the reference of last character. |
Iterator begin() | It returns the reference of first character. |
Int capacity() | It returns the allocated space for the string. |
Const_iterator cbegin() | It points to the first element of the string. |
Const_iterator cend() | It points to the last element of the string. |
Void clear() | It removes all the elements from the string. |
Const_reverse_iterator crbegin() | It points to the last character of the string. |
Const_char* data() | It copies the characters of string into an array. |
Bool empty() | It checks whether the string is empty or not. |
String& erase() | It removes the characters as specified. |
Char& front() | It returns a reference of the first character. |
String& operator+=() | It appends a new character at the end of the string. |
String& operator=() | It assigns a new value to the string. |
Char operator[](pos) | It retrieves a character at specified position pos. |
Int rfind() | It searches for the last occurrence of the string. |
Iterator end() | It references the last character of the string. |
Reverse_iterator rend() | It points to the first character of the string. |
Void shrink_to_fit() | It reduces the capacity and makes it equal to the size of the string. |
Char* c_str() | It returns pointer to an array that contains null terminated sequence of characters. |
Const_reverse_iterator crend() | It references the first character of the string. |
Reverse_iterator rbegin() | It reference the last character of the string. |
Void reserve(inr len) | It requests a change in capacity. |
Allocator_type get_allocator(); | It returns the allocated object associated with the string. |
Reference Books
1 “Thinking in C++”, Volume 1 and 2 by Bruce Eckel, Chuck Allison, Pearson
Education
2 “Mastering C++”, 1/e by Venugopal, TataMcGraw Hill.
3 “Object Oriented Programming with C++”, 3/e by E. Balaguruswamy, Tata
McGraw Hill.
4 “Starting Out with Object Oriented Programming in C++”, by Tony Gaddis,
Wiley India.