#include<iostream>
using namespace std;
int main(){
cout << "Hello World" << endl;
return 0;
}
The g++ is a compiler that is used to compile programs written in the C++ programming language. It is part of the GNU Compiler Collection (GCC).
g++ file.cpp
g++ file.cpp -o exe_name
./a.out
./exe_name
The iostream
(or input-output stream) is a C++ Standard Library (or header file) that provides definitions for the istream
and ostream
classes. It is used to read input from a stream of characters, such as a console or file, and write output data to the console or file.
The ostream
(or output stream) is used to write a stream of characters as output to the console or a file.
Console Output : The cout
(or console-output) is a predefined object of the ostream class. It is used with a stream insertion operator (<<
) to display output.
cout << "Hello World";
cout << "\nValue of X is " << x;
End Line : The endl
(or end-line) is a predefined object of the ostream class. It is used to insert new line characters and flush the stream.
cout << "Hello World" << endl;
The istream
(or input stream) is used to handle input operations from a stream of characters (such as the console or a file).
Console Input : The cin
(or console input) is a predefined object of the istream class. It is used with the stream extraction operator (>>
) to read input from the console.
cin >> n;
cin >> a >> b >> c;
The escape sequences are special non-printing characters that are used to control the printing behavior of the output stream objects.
Escape Char | Description |
---|---|
\a |
Alarm or beep sound |
\b |
Backspace |
\f |
Form feed |
\n |
New line |
\r |
Return |
\t |
Tab space |
\\ |
Backslash |
\' |
Single quote |
\? |
Question mark |
\nnn |
Octal number |
\xhh |
Hexadecimal number |
\0 |
Null |
//
is used for single-line comment.
// This is single-line comment.
cout << "Hello World"; // This is comment
/* */
is used for multi-line comment.
/* This is
multi-line comment. */
int x = 22; /* This is multi-line
comment. */
data_type variable_name;
int a;
int x, y, z = 17;
int n = 22;
string name = "Mandar";
The Local variables are declared inside a function or block and can be used only by statements that are inside that function or block. The Global variables are defined outside of all the functions, can be accessed by any function, and hold their value throughout the life of program.
#include<iostream>
using namespace std;
// Global Variables :
float f = 17.22;
int n = 0;
int main(){
// Local Variables :
int x, y = 22;
float a, b;
a = b = 22.17;
return 0;
}
A data type specifies the type of data that a variable can store such as integer, floating, character, etc.
A primitive type is predefined and built into a programming language. It is named with a reserved keyword.
Date Type | Size | Description |
---|---|---|
bool |
1 byte | boolean values (true or false ) |
char |
1 byte | single character, letter, number or ASCII values |
int |
4 byte | integers (non-decimals) |
float |
4 byte | fractional numbers (upto 7 decimal digits) |
double |
8 byte | fractional numbers (upto 15 decimal digits) |
void |
- | represents no type or absence of type |
Modifiers are prefix keywords that change the properties of the basic primitive data type.
Date Type | Size | Description |
---|---|---|
signed |
4 byte | only negative numbers |
unsigned |
4 byte | only positive numbers |
short |
2-4 byte | small numbers (machine dependent) |
long |
4-8 byte | large numbers (machine dependent) |
A type qualifier is used to refine the declaration of a variable, a function, and parameters.
Keyword | Description |
---|---|
const |
constant (read-only variables that can't be reassigned) |
volatile |
volatile variables' value could change unexpectedly, and no optimization is done on them. |
restrict |
restrict is used for pointers, which tells the compiler that a restricted pointer is the only way to access the object pointed at it (no other pointer can point to the same object). |
const int COUNT = 1;
The typedef
keyword assigns a new name or alias to an existing data type.
typedef type newname;
typedef int feet;
feet distance;
distance = 2002;
cout << "Distance = " << distance << endl;
The Storage class defines the scope (visibility) and life-time of variables and/or functions within a C++ program.
class type name
It is the default storage class for all local variables.
It specifies that the symbol has external linkage to an external file or scope. The external storage class simply tells us that the variable is defined elsewhere and not within the same block where it is used.
When a variable is declared static, a single copy of the variable is created (memory is allocated only once) and shared among all objects at the class level. All instances of the class share the same static variable. The static is a property of the class, not the object, and hence the object of the class can't use it to access it; it can be called using the class name. The value of static variables and data members persists until the end of the program.
Register variables are stored in the processor register instead of memory (deprecated).
It allows a member of an object to override a const member function (applies only to class objects).
Class | Lifetime | Visibility | Default Value |
---|---|---|---|
auto |
function/block | local | garbage |
extern |
throughout program | global | zero |
static |
throughout program | local | zero |
register |
function/block | local | garbage |
mutable |
class | local | garbage |
auto int x;
register int amount = 0;
static int count = 1;
Operator | Description |
---|---|
+ |
Addition |
- |
Substraction |
* |
Multiplication |
/ |
Division |
% |
Modulus |
++ |
Increment |
-- |
Decrement |
Operator | Description |
---|---|
== |
Equal to |
!= |
Not equal to |
> |
Greater than |
< |
Less than |
>= |
Greater than or equal to |
<= |
Less than or equal to |
Operator | Description |
---|---|
&& |
Logical and |
|| |
Logical or |
! |
Logical not |
Operator | Description |
---|---|
& |
Bitwise AND |
| |
Bitwise OR |
^ |
Bitwise XOR |
~ |
One's Complement (unary) |
<< |
Left Shift Operator |
>> |
Right Shift Operator |
The sizeof()
operator or function returns the amount of memory that is allocated to data types in bytes.
int x = 22;
cout << sizeof(x);
[condition] ? [expr_1] : [expr_2]
If the condition is true, then expression 1 is evaluated; otherwise, expression 2 is evaluated.
int a=5, b=10, large;
large = a > b ? a : b;
cout << "Largest number is " << large << endl;
Typecasting is the conversion of one data type into another by using a casting operator.
type(expression)
(type)expression
// Casting float into int:
cout << int(22.17);
cout << (int)17.22;
The dot operator (.
) and the arrow operator (->
) are used to reference individual members of classes, structures, and unions. To access members through a pointer, the arrow operator is used.
struct Classroom {
int roll;
char name[20];
};
int main(){
// Using dot operator :
struct Classroom s = { 17, "Mandar" };
cout << "Roll: " << s.roll << "\nName: "<< s.name << endl;
// Using arrow operator (pointer) :
struct Classroom *sp = &s;
cout << "Roll: " << sp->roll << "\nName: "<< sp->name;
return 0;
}
The referencing operator (&
) is used for accessing the memory location of a variable, and the dereferncing operator (*
) is used for accessing the value stored at the memory location.
// Referencing:
int v = 22;
cout << "Address of v is " << &v;
// Dereferencing:
cout << "\nValue of v is " << *(&v);
The scope resolution operator (::
) is used to access variables, functions, or classes defined in a specific scope or namespace. It can be used to define the member function outside of the class and to access the static members of a class.
int x = 100;
int main(){
int x = 50;
cout << "Local X is " << x << endl;
cout << "Global X is " << ::x << endl;
return 0;
}
if(condition){
// statements_if_true
}
int a=10, b=20;
if(a > b){
cout << "A is larger than B";
}
if(condition){
// statements_if_true
} else {
// statements_if_false
}
int a=10, b=20;
if(a > b){
cout << "A is greater than B";
} else {
cout << "A is smaller than B";
}
if(condition){
// statements_if_true
} else if (condition) {
// statements_if_true
} else {
// statements_if_false
}
int a=10, b=20;
if(a > b){
cout << "A is greater than B";
} else if (a < b) {
cout << "A is smaller than B";
} else {
cout << "A is equal to B";
}
int age = 22;
if(age > 0){
if(age < 18)
cout << "You are young";
else if ( age >= 18)
cout << "You are adult";
} else {
if(age < 0)
cout << "Age cannot be negative";
else
cout << "Age cannot be zero";
}
A switch statement allows a variable to be tested for equality against a list of values.
switch(expression){
case constant-expression-1 :
statement(s);
break;
case constant-expression-2 :
statement(s);
break;
case constant-expression-N :
statement(s);
break;
default :
statement(s);
}
int day = 3;
switch(day){
case 1 :
cout << "Mon";
break;
case 2 :
cout << "Tue";
break;
case 3 :
cout << "Wed";
break;
case 4 :
cout << "Thu";
break;
case 5 :
cout << "Fri";
break;
case 6 :
cout << "Sat";
break;
case 7 :
cout << "Sun";
break;
default :
cout << "Incorrect Day!";
}
Generally, when the number of iterations is unknown, the while loop is used.
while(condition) {
statement(s);
}
int n = 1;
while(n <= 5){
cout << "Hello World";
n++;
}
do {
statement(s);
} while(condition);
int n = 1;
do {
cout << "Hello World";
n++;
} while(n <= 5)
Generally, when the number of iterations is known, the for loop is used.
for ( init; condition; increment ){
statement(s);
}
for(int i=1; i<=5; i++){
cout << "Hello World";
}
for(int i=1; i<=5; i++)
for(int j=1; j<=i; j++)
cout << "Hello World";
Terminates the loop or switch statement and transfers execution to the statement immediately following the loop or switch.
break;
int n = 1;
while(n <= 100){
if (n == 22) break;
cout << "Hello World";
n++;
}
This causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating.
continue;
int n = 1;
while(n <= 100){
if (n%2 == 0) continue;
cout << "Hello World";
n++;
}
Transfers control to the labelled statement.
goto label;
labal:
statement(s);
int n;
INPUT:
cout << "Enter Odd Number :";
cin >> n;
if (n%2 == 0) goto INPUT;
Strings are one-dimensional arrays of characters terminated by the null character '\0'. There are two ways of using strings in C++ :
Declaring a string as a character array as in the C language
char name[];
char greet[] = "Hello World";
char name[10];
name = "Mandar";
The standard C++ library provides a string class. For this, we must include the library/header file <string>
.
string name;
#include<iostream>
#include<string>
using namespace std;
int main(){
string greet = "Hello World";
cout << greet << endl;
cout << "String Length is " << greet.length() << endl;
return 0;
}
Function | Description |
---|---|
str.length() |
Returns the length of string |
str.append(string) |
Appends the string at the end of str. |
str.copy(string,len,pos) |
Copies c-style string of size (len) from position (pos) to str |
str.replace(pos,len,string) |
Replace string of size (len) from position (pos) in str |
str.compare(str2) |
Returns 0 if both are the same; less than 0 if str<str2; greater than 0 if str>str2. |
str.find(string) |
Find first occurance of string in str and returns the position |
str.substr(pos,len) |
Returns sub-string of length (len) from the string from position (pos) |
str.c_str() |
Returns C string equivalent (null-terminated sequence of characters) |
An array is a fixed-size sequential collection of elements of the same type. All arrays consist of contiguous memory locations. Array indexes start with 0: [0] is the first element. Arrays cannot be reinitialized.
type name[size];
type name[N] = { element1, element2, ..., elementN };
type name[] = { element1, element2, ..., elementN };
array[index];
sizeof(array) / sizeof(type);
int num[] = { 1, 2, 3, 4, 5 };
int n = num[2];
int square_num[5];
int size = sizeof(square_num) / sizeof(int);
for (int i = 0; i < size; i++)
square_num[i] = (i+1)*(i+1);
for(int i=0; i < size; i++)
cout << square_num[i] << " ";
A multi-dimensional array is an array of arrays.
type name[size1][size2]...[sizeN];
int arr[4][2] = { {1,2}, {3,4}, {5,6}, {7,8} };
for( int i=0; i<4; i++)
for( int j=0; j<2; j++)
cout << arr[i][j] << " ";
int num[5] = { 1, 2, 3, 4, 5};
int *p;
p = num;
cout << "Array values using pointer:" << endl;
for ( int i = 0; i < 5; i++ )
cout << *(p + i) << endl;
cout << "Array values using num as address:" << endl;
for ( int i = 0; i < 5; i++ )
cout << *(num + i) << endl;
cout << "Array values by incrementing pointer address:" << endl;
for ( int i = 0; i < 5; i++ )
cout << *(p++) << endl;
int sumOfNum(int num[], int size){
int sum=0;
for (int i=0; i < size; i++){
sum += num[i];
}
return sum;
}
int main(){
int num[5] = { 1, 2, 3, 4, 5};
int size = sizeof(num)/sizeof(int);
cout << "Sum of numbers is " << sumOfNum(num,size) << endl;
return 0;
}
#include<iostream>
#include<time.h>
using namespace std;
// Get array of random numbers -
int* getArray(){
static int num[5];
// set the seed
srand((unsigned)time(NULL));
for (int i = 0; i < 5; i++)
num[i] = rand()%10;
return num;
}
int main(){
int *p;
p = getArray();
for (int i = 0; i < 5; i++)
cout << *(p++) << " ";
return 0;
}
class Employee {
private:
int id;
string name;
public:
void setEmpID(int id){
this->id = id;
}
int getEmpID(){
return id;
}
void setEmpName(string name){
this->name = name;
}
string getEmpName(){
return name;
}
};
int main(){
// Creating array of type class:
Employee emp[4];
string emp_name[4] = {"Vinit", "Amit", "Ankit", "Sumit"};
for(int i=0; i<4; i++){
emp[i].setEmpID(i+101);
emp[i].setEmpName(emp_name[i]);
}
for(int i=0; i<4; i++){
cout << "\nEmployee ID: " << emp[i].getEmpID() << endl;
cout << "Employee Name: " << emp[i].getEmpName() << endl;
}
return 0;
}
class Employee {
private:
int id;
string name;
public:
Employee(int id, string name){
this->id = id;
this->name = name;
}
int getEmpID(){
return id;
}
string getEmpName(){
return name;
}
};
int main(){
// Creating array of type class with constructor:
Employee emp[4] = { Employee(101,"Vinit"), Employee(102,"Amit"), Employee(103,"Sumit"), Employee(104,"Ankit") };
for(int i=0; i<4; i++){
cout << "\nEmployee ID: " << emp[i].getEmpID() << endl;
cout << "Employee Name: " << emp[i].getEmpName() << endl;
}
return 0;
}
class Employee {
private:
int id;
string name;
public:
void setEmpID(int id){
this->id = id;
}
int getEmpID(){
return id;
}
void setEmpName(string name){
this->name = name;
}
string getEmpName(){
return name;
}
};
int main(){
// Creating dynamic array of type class:
Employee* emp = new Employee[4];
string emp_name[4] = {"Vinit", "Amit", "Ankit", "Sumit"};
for(int i=0; i<4; i++){
emp[i].setEmpID(i+101);
emp[i].setEmpName(emp_name[i]);
}
for(int i=0; i<4; i++){
cout << "\nEmployee ID: " << emp[i].getEmpID() << endl;
cout << "Employee Name: " << emp[i].getEmpName() << endl;
}
return 0;
}
A pointer is a variable which holds the memory address of another variable, i.e., it stores the address of a memory location.
&
) is used for this.*
) is used for this.type *name;
int n = 22;
// Referencing:
int *p = &n;
cout << "Adrress: " << p;
// Dereferencing:
cout << "\nValue: " << *p;
A pointer to a pointer is a form of multiple indirection or a chain of pointers where pointer contains the adress of another pointer.
type **name;
int n = 22;
int *p = &n;
int **pp = &p;
cout << "n = " << n << endl;
cout << "p = " << *p << endl;
cout << "pp = " << **pp << endl;
A pointer that is assigned NULL is called a null pointer. It does not point to any memory location; it represents an invalid memory location. It is used to initialise a pointer when that pointer has not been assigned any valid address yet.
int *p = NULL;
A pointer with no associated data type is referred to as a void pointer. It can point to data of any type. We cannot directly dereference a void pointer; it must first be typecast before dereferencing.
int n = 22;
void *p = &n;
cout << *(int*)p << endl;
Wild pointers are also known as uninitialized pointers. These pointers usually point to some arbitrary memory location and may cause the program to crash or misbehave.
A dangling pointer is a pointer that points to some non-existing memory location.
A reference variable is an alias, that is, another name for an already existing variable.
type &name = var;
string food = "Veg Rice";
string &meal = food;
Functions are blocks of statements that perform a specific task. It is reusable code that can be called anywhere in the program.
return_type functionName(parameter_list);
return_type functionName(){
// body of function
}
functionName();
// Function declaration:
void greet();
int sum(int, int);
// Function definition:
void greet(){
cout << "Hello World";
}
int sum(int a, int b){
return a+b;
}
int main(){
// Calling function:
greet();
sum(17,22);
return 0;
}
A function with a return type other than void returns a value.
int sum(int a, int b){
return a+b;
}
int main(){
cout << "Addition is " << sum(1,2) << endl;
return 0;
}
When a function is called, the values that are passed in the call are called arguments. They are also called actual parameters. The values that are written at the time of the function prototype and the definition of the function are called parameters. They are also called formal parameters.
// Here name is parameter
void greet(string name){
cout << "Hello " << name << endl;
}
int main(){
string name = "Mandar";
// Here name is argument
greet(name);
return 0;
}
Arguments are passed to functions as formal parameters while calling the function. There are three ways in which we can pass parameters to a function.
This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.
void swap(int a, int b){
a = a + b;
b = a - b;
a = a - b;
}
int main(){
int a=17, b=22;
cout << "Before Swapping :\nA = " << a << "\nB = " << b << endl;
swap(a, b);
cout << "After Swapping :\nA = " << a << "\nB = " << b << endl;
return 0;
}
This method copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument.
void swap(int *a, int *b){
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
int main(){
int a=17, b=22;
cout << "Before Swapping :\nA = " << a << "\nB = " << b << endl;
swap(&a, &b);
cout << "After Swapping :\nA = " << a << "\nB = " << b << endl;
return 0;
}
This method copies the reference of an argument into the formal parameter. Inside the function, the reference is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument.
void swap(int &a, int &b){
a = a + b;
b = a - b;
a = a - b;
}
int main(){
int a=17, b=22;
cout << "Before Swapping :\nA = " << a << "\nB = " << b << endl;
swap(a, b);
cout << "After Swapping :\nA = " << a << "\nB = " << b << endl;
return 0;
}
When no parameters are passed or some arguments are left blank while calling the function, the default values are used.
int sum(int a=2, int b=9){
return a+b;
}
int main(){
cout << "Sum is " << sum(1,2);
cout << "\nSum is " << sum(22);
cout << "\nSum is " << sum();
return 0;
}
Function overloading is a feature of object-oriented programming. When two or more functions have the same name but different numbers and types of parameters, the corresponding function is overloaded based on the parameters; this is called function overloading. This is an example of a compile-time polymorphism.
void sum(){
int a, b;
cout << "\nEnter Two Numbers : ";
cin >> a >> b;
cout << "Sum is " << a+b;
}
int sum(int a, int b){
return a+b;
}
int sum(int a, int b, int c){
return a+b+c;
}
float sum(float a, float b){
return a+b;
}
int main(){
cout << "Sum is " << sum(2,9);
cout << "\nSum is " << sum(1,2,3);
cout << "\nSum is " << sum(3.2f,2.4f);
sum();
return 0;
}
The process in which a function calls itself directly or indirectly is called recursion, and the corresponding function is called a recursive function.
int sum(int n){
if(n != 0) return n + sum(n-1);
else return n;
}
int main(){
cout << "Sum is " << sum(10);
return 0;
}
In an inline function, when it is called, the whole code of the inline function gets inserted or substituted at the point of the inline function call by the compiler. Inlining is only a request to the compiler, not a command, and the compiler may ignore the request for inlining.
inline int max(int a, int b){
return (a > b) ? a : b;
}
int main(){
cout << "Max of number is " << max(12,10) << endl;
return 0;
}
A function is defined without any class and is called by its name only. A method also works the same as that of a function, but it is defined inside a class and invoked by its reference or object only.
class Name {
public:
// printm is method
void printm(string name){
cout << name << endl;
}
};
// printf is function
void printf(string name){
cout << name << endl;
}
int main(){
Name ob;
// printm is method
ob.printm("Mandar");
// printf is function
printf("Patkar");
return 0;
}
An enumeration is a user-defined data type that consists of integral constants. Default values are 0, 1, 2, and so on. To define an enumeration, the keyword enum
is used.
enum Week { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
enum Color { Red, Green, Blue };
int main(){
Week day;
day = Monday;
cout << "Day is " << day << endl;
Color clr = Blue;
cout << "Color is " << clr << endl;
return 0;
}
Structures (also called structs) are a way to group several related variables into one place. Each variable in the structure is referred to as a member of the structure. A structure can contain many different data types (int, string, bool, etc.). To access members of a structure, the member access operator (.
) is used. We can't assign a character array (a string) to a structure, but we can copy it.
struct Name {
type name;
type name;
....;
} var;
#include <iostream>
#include <cstring>
using namespace std;
struct Books {
int book_id;
char title[50];
char author[50];
} book1;
int main(){
// Book 1 Specification:
book1.book_id = 01;
strcpy( book1.title, "The C++ Programming Language");
strcpy( book1.author, "Bjarne Stroustrup");
cout << "Title: " << book1.title << endl;
cout << "Author: " << book1.author << endl;
// Book 2 Specification: (short-hand syntax)
struct Books book2 = { 02, "Beginning C++ Programming", "Richard Grimes"};
cout << "Title: " << book2.title << endl;
cout << "Author: " << book2.author << endl;
return 0;
}
Self-referential structures are those structures in which one or more pointers point to another structure of the same type.
struct Name {
int p;
struct Name *pointer;
};
struct Classroom {
int roll;
char name[10];
struct Classroom *ptr;
};
int main(){
struct Classroom c1 = { 22, "Mandar", NULL };
c1.ptr = &c1;
cout << "Roll: " << c1.ptr->roll << "\nName: "<< c1.ptr->name;
return 0;
}
struct Classroom {
int roll;
char name[10];
};
void print(struct Classroom c){
cout << "Roll: " << c.roll << endl;
cout << "Name: "<< c.name << endl;
}
int main(){
struct Classroom c1 = {22, "Mandar"};
print(c1);
return 0;
}
struct Classroom {
int roll;
char name[10];
};
void print(struct Classroom c[]){
for (int i=0; i<2; i++){
cout << "Roll: " << c[i].roll << endl;
cout << "Name: "<< c[i].name << endl;
}
}
int main(){
struct Classroom c[2] = { {17, "Vinit"}, {22, "Vinita"} };
print(c);
return 0;
}
struct Classroom {
int roll;
char name[10];
};
struct Classroom edit(struct Classroom c){
c.roll=22;
strcpy(c.name,"Vinita");
return c;
}
void print(struct Classroom c){
cout << "Roll: " << c.roll << "\nName: "<< c.name << endl;
}
int main(){
struct Classroom c1 = {17, "Vinit"};
print(c1);
c1=edit(c1);
print(c1);
return 0;
}
struct Classroom {
int roll;
char name[10];
};
void print(struct Classroom *c_ptr){
cout << "Roll: " << c_ptr->roll << endl;
cout << "Name: "<< c_ptr->name << endl;
}
int main(){
struct Classroom c1 = {22, "Mandar"};
print(&c1);
return 0;
}
A class is a blueprint or template for creating objects that define a set of properties and methods that are common to all objects of that type. It serves as a blueprint that defines the characteristics and behaviours of objects.
class Student {
private:
// Fields :
int roll = 22;
string name = "Mandar";
public:
// Methods :
int printRoll(){
return roll;
}
string printName(){
return name;
}
void studentInfo();
};
Method definition outside class using the scope resolution operator (::
).
void Student::studentInfo(){
cout << "Roll : " << printRoll() << endl;
cout << "Name : " << printName() << endl;
}
An object is an instance of a class that encapsulates data and behaviour. An object is created from a class blueprint and can be used to access the properties and methods defined in the class. When a class is defined, no memory is allocated, but when it is instantiated (i.e., an object is created), memory is allocated.
// Creating Object :
Student s1;
// Calling method with Objects :
s1.studentInfo();
// Creating object:
Student s1;
// Creating pointer object:
Student *p_ob;
p_ob = &s1;
// Calling method with pointer object:
p_ob->studentInfo();
Access specifiers define how the members (attributes and methods) of a class can be accessed. Default access specifier is private.
class MyClass {
public: // Public access specifier
int pu;
protected: // Protected access specifier
int pt;
private: // Private access specifier
int pr;
};
int main(){
MyClass ob;
ob.pu = 25; // Allowed (public)
ob.pt = 75; // Error: Not allowed (protected)
ob.pr = 50; // Error: Not allowed (private)
return 0;
}
The keyword this
is a pointer that refers to the current instance of the class. The compiler supplies this pointer implicitly along with the names of functions. It is passed as a hidden argument to all non-static member function calls and is available as a local variable within the body of all non-static functions.
class Student {
private:
int roll;
string name;
public:
// Constructor :
Student(int roll, string name){
this->roll = roll;
this->name = name;
}
void studentInfo(){
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
}
void print(){
this->studentInfo();
}
};
int main(){
Student s1(22, "Mandar");
s1.print();
return 0;
}
When a variable or method is declared static
, a single copy of the variable is created (memory is allocated only once) and shared among all objects at the class level. All instances of the class share the same static variable. The static is a property of the class, not the object, and hence the object of the class can't use it to access it; it can be called using the class name. The value of static variables and data members persists until the end of the program.
class MyClass {
public:
// static variable :
static int count;
MyClass(){
count++;
}
void printCount(){
cout << count << " objects created" << endl;
}
};
// Initialize static member :
int MyClass::count = 0;
int main(){
MyClass ob1, ob2;
ob1.printCount();
MyClass ob3;
ob3.printCount();
MyClass ob4, ob5;
cout << "Total objects : " << MyClass::count << endl;
return 0;
}
class MyClass {
public:
// static variable :
static int count;
MyClass(){
count++;
}
static void printCount(){
cout << count << " objects created" << endl;
}
};
// Initialize static member :
int MyClass::count = 0;
int main(){
MyClass ob1;
MyClass::printCount();
MyClass ob2, ob3;
MyClass::printCount();
return 0;
}
A friend class or function can access the private and protected members of a class. It is declared using the friend
keyword inside the body of the class. A friend function can be a member of another class or a global function.
class ClassName {
friend return_type functionName(arguments);
}
class Student {
private:
int roll;
string name;
public:
// Constructor :
Student(int roll, string name){
this->roll = roll;
this->name = name;
}
friend class Info;
};
class Info {
public:
void studentInfo(){
Student s(22, "Mandar");
cout << "Roll : " << s.roll << endl;
cout << "Name : " << s.name << endl;
}
};
int main(){
Info ob;
ob.studentInfo();
return 0;
}
class B;
class A {
private:
int x;
public:
// Constructor :
A() : x(10){}
friend void addNum(A, B);
};
class B {
private:
int y;
public:
// Constructor :
B() : y(20){}
friend void addNum(A, B);
};
void addNum(A a, B b){
cout << "Addition is " << a.x + b.y << endl;
}
int main(){
A a;
B b;
addNum(a,b);
return 0;
}
It is a special method that is automatically called when an object of a class is created. The constructor has the same name as the class, it is always public, and it does not have any return value.
class Student {
private:
int roll;
string name;
public:
// Constructor (parameterized) :
Student(int r, string n){
cout << "Constructor is called" << endl;
roll = r;
name = n;
}
void studentInfo(){
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
}
};
int main(){
Student s1(22, "Mandar");
s1.studentInfo();
return 0;
}
The copy constructor is a constructor that creates an object by initialising it with an already created object of the same class. The copy constructor takes a reference to an object of the same class as an argument. There will always be only one copy constructor which can be either defined by the user or the compiler. The compiler implicitly defines the default copy constructor if it is not defined by the programmer.
class Student {
private:
int roll;
string name;
public:
// Constructor :
Student(int r, string n){
roll = r;
name = n;
}
// User Defined Copy Constructor (explicitly defined) :
Student(const Student &s){
roll = s.roll;
name = s.name;
}
void studentInfo(){
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
}
};
int main(){
Student s1(22, "Mandar");
s1.studentInfo();
// Copy Constructor :
Student s2=s1;
s2.studentInfo();
Student s3(s2);
s3.studentInfo();
return 0;
}
The initialization lists are used to initialise fields.
class Student {
private:
int roll;
string name;
int std;
public:
// Constructor: Initialization List :
Student(int r, string n, int s): name(n), std(s){
roll = r;
}
void studentInfo(){
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
cout << "Std : " << std << "th" << endl;
}
};
int main(){
Student s1(22, "Mandar", 9);
s1.studentInfo();
return 0;
}
class School {
private:
string sch_name;
public:
School(string name) : sch_name(name) {}
string schoolName(){
return sch_name;
}
};
class Student : public School {
private:
int roll;
string name;
int std;
public:
// Constructor: Initialization List :
Student(string sch_name, int r, string n, int s): School(sch_name), name(n), std(s){
roll = r;
}
void studentInfo(){
cout << "School : " << schoolName() << endl;
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
cout << "Std : " << std << "th" << endl;
}
};
int main(){
Student s1("Vartak", 22, "Mandar", 9);
s1.studentInfo();
return 0;
}
It is a special method that is automatically called when an object of its class goes out of scope. The destructor has the same name as the class, is preceded by a tilde (~
) symbol, is always public, and does not have any return value.
class Student {
private:
int roll;
string name;
public:
// Constructor :
Student(int r, string n){
cout << "Constructor is called" << endl;
roll = r;
name = n;
}
void studentInfo(){
cout << "Roll : " << roll << endl;
cout << "Name : " << name << endl;
}
// Destructor :
~Student(){
cout << "Destructor is called" << endl;
}
};
int main(){
Student s1(22, "Mandar");
s1.studentInfo();
return 0;
}
Inheritance is a feature or a process in which new classes are created from existing ones. The new class created is called a "derived class" or "child class," and the existing class is known as the "base class" or "parent class." The derived class is now said to be inherited from the base class. The inherited class acquires all the properties and behaviours of the parent class. This allows programmers to reuse, extend, or modify the attributes and behaviours of existing classes. The private members of the base class are never inherited.
Base Class Visibility | Derived Class Visibility | ||
---|---|---|---|
Public | Private | Protected | |
Public | Public | Private | Protected |
Protected | Protected | Private | Protected |
Private | Not Inherited | Not Inherited | Not Inherited |
Single inheritance is defined as the inheritance in which a derived class is inherited from only one base class.
// Base or Parent Class :
class Bank {
private:
string bank_name;
public:
Bank(string bank) : bank_name(bank) {}
string printBank(){
return bank_name;
}
};
// Derived or Child Class :
class Account : public Bank {
private:
string type;
int num;
public:
Account(string bank, string type, int num) : Bank(bank), type(type), num(num) {}
string printAccountType(){
return type;
}
int printAccountNum(){
return num;
}
};
int main(){
Account person1("SBI","Saving",1234);
cout << "Bank : " << person1.printBank() << endl;
cout << "Account Type : " << person1.printAccountType() << endl;
cout << "Account Number : " << person1.printAccountNum() << endl;
return 0;
}
Multiple inheritance is defined as the inheritance in which a derived class is inherited from two or more base classes.
// Base Class 1 :
class Father {
private:
string fname = "Vinit Patil";
public:
string printFName(){
return fname;
}
};
// Base Class 2 :
class Mother {
private:
string mname = "Vinita Patil";
public:
string printMName(){
return mname;
}
};
// Derived Class :
class Son : public Father, public Mother {
private:
string sname = "Amit Patil";
public:
string printSName(){
return sname;
}
};
int main(){
Son s1;
cout << "Name : " << s1.printSName() << endl;
cout << "Father Name : " << s1.printFName() << endl;
cout << "Mother Name : " << s1.printFName() << endl;
return 0;
}
In multiple inheritances, when one class is derived from two or more base classes, there may be a possibility that the base classes have functions with the same name, and the derived class may not have functions with the same name as those of its base classes. If the derived class object needs to access one of the similarly named member functions of the base classes then it results in ambiguity because the compiler gets confused about which base’s class member function should be called. To solve this ambiguity scope resolution operator (::
) is used.
objectName.ClassName::functionName();
// Base Class 1 :
class Father {
private:
string fname = "Vinit Patil";
public:
string printName(){
return fname;
}
};
// Base Class 2 :
class Mother {
private:
string mname = "Vinita Patil";
public:
string printName(){
return mname;
}
};
// Derived Class :
class Son : public Father, public Mother {
private:
string sname = "Amit Patil";
public:
string printSName(){
return sname;
}
};
int main(){
Son s1;
cout << "Name : " << s1.printSName() << endl;
// Resolve ambiguity using scope resolution operator :
cout << "Father Name : " << s1.Father::printName() << endl;
cout << "Mother Name : " << s1.Mother::printName() << endl;
return 0;
}
Multilevel inheritance is defined as the inheritance in which a derived class is inherited from another derived class.
// Base Class :
class GrandFather {
public:
int age_g;
GrandFather(int g) : age_g(g) {}
string gname = "Avnish Patil";
string printGName(){
return gname;
}
};
// Derived & Base Class :
class Father : public GrandFather {
public:
int age_f;
Father(int g, int f) : GrandFather(g), age_f(f) {}
string fname = "Vinit Patil";
string printFName(){
return fname;
}
};
// Derived Class :
class Son : public Father {
public:
int age_s;
Son(int g, int f, int s) : Father(g,f), age_s(s) {}
string sname = "Amit Patil";
string printSName(){
return sname;
}
};
int main(){
Son s1(95,75,30);
cout << "I am " << s1.printSName() << " my age is " << s1.age_s << endl;
cout << "My father name is " << s1.printFName() << " his age is " << s1.age_f << endl;
cout << "My grand father name is " << s1.printGName() << " his age is " << s1.age_g << endl;
return 0;
}
Hierarchical inheritance is defined as the type of inheritance in which more than one derived class is inherited from only one base class.
// Base Class :
class Father {
private:
string fname = "Vinit Patil";
public:
string printFName(){
return fname;
}
};
// Derived Class 1 :
class Son : public Father {
private:
string sname = "Amit Patil";
public:
string printSName(){
return sname;
}
};
// Derived Class 2 :
class Daughter : public Father {
private:
string dname = "Amita Patil";
public:
string printDName(){
return dname;
}
};
int main(){
Son s1;
cout << "Father Name : " << s1.printFName() << endl;
cout << "Son Name : " << s1.printSName() << endl;
Daughter d1;
cout << "\nFather Name : " << d1.printFName() << endl;
cout << "Daughter Name : " << d1.printDName() << endl;
return 0;
}
Inheritance that combines multiple types of inheritance is known as hybrid inheritance.
class Shape {
public:
Shape(){
cout << "This is Shape" << endl;
}
};
class Circle : public Shape {
public:
Circle(){
cout << "This is Circle" << endl;
}
};
class Rectangle : public Shape {
public:
Rectangle(){
cout << "This is Rectangle" << endl;
}
};
class Square : public Rectangle {
public:
Square(){
cout << "This is Square" << endl;
}
};
int main(){
// Single Inheritance : Shape -> Circle
Circle c1;
// Hierarchical Inheritance : Shape -> Circle & Rectangle
Circle c2
Rectangle r1;
// Multilevel Inheritance : Shape -> Rectangle -> Square
Square s1;
return 0;
}
Virtual inheritance is a C++ technique that ensures only one copy or instance of a base class's member variables should be present in the inheritance hierarchy, even if the class is inherited multiple times. This is done with the virtual
keyword. Objects of class Cuboid have two paths to call constructor of class Shape; hence, it will result in ambiguity, called the "diamond problem." Virtual inheritance can be used to resolve this ambiguity in inheritance.
class Shape {
public:
Shape(){
cout << "This is Shape" << endl;
}
};
class Rectangle : virtual public Shape {
public:
Rectangle(){
cout << "This is Rectangle" << endl;
}
};
class Square : virtual public Rectangle {
public:
Square(){
cout << "This is Square" << endl;
}
};
class Cuboid : virtual public Rectangle, virtual public Square {
public:
Cuboid(){
cout << "This is Cuboid" << endl;
}
};
int main(){
/* Shape
/ \
Rectangle Square
\ /
Cuboid
*/
Cuboid cb;
return 0;
}
The word "polymorphism" means having many forms. That is, the same entity (function or operator) behaves differently in different scenarios, so a single action can be performed in different ways.
Compile-time polymorphism, also called static polymorphism, is resolved (which method to execute) during compile time and is achieved through method overloading and operator overloading. It is also called static binding or early binding. Binding is the association of names with classes. In the case of static binding, names can be associated with classes during compilation time.
Method overloading is a feature of object-oriented programming. When two or more methods have the same name but different numbers and types of parameters, the corresponding method is overloaded based on the parameters; this is called method overloading. This is an example of a compile-time polymorphism.
class Sum {
public:
void sum(){
int a, b;
cout << "\nEnter Two Numbers : ";
cin >> a >> b;
cout << "Sum is " << a+b << endl;
}
int sum(int a, int b){
return a+b;
}
int sum(int a, int b, int c){
return a+b+c;
}
float sum(float a, float b){
return a+b;
}
};
int main(){
Sum s1;
cout << "Sum is " << s1.sum(2,9);
cout << "\nSum is " << s1.sum(1,2,3);
cout << "\nSum is " << s1.sum(3.2f,2.4f);
s1.sum();
return 0;
}
The C++ language has the ability to provide the operators with a special meaning for a data type; this ability is known as "operator overloading." Operators can be used for user-defined classes. It is an idea of giving special meaning to an existing operator in C++ without changing its original meaning.
::
).
).*
)?:
)sizeof()
)The unary increment operator (++
) is overloaded for incrementing objects.
class OperatorOL {
private:
int count = 0;
public:
// Operator ++ overloaded :
void operator ++ (){
++count;
}
int printCount(){
return count;
}
};
int main(){
OperatorOL ob;
while(ob.printCount() < 5)
++ob;
cout << "Count = " << ob.printCount() << endl;
return 0;
}
The binary addition operator (+
) is overloaded for the addition of two objects.
class Complex {
private:
int real, imag;
public:
Complex(int r, int i){
real = r;
imag = i;
}
void print(){
cout << real << " + i" << imag << endl;
}
// Operator + overloaded :
Complex operator + (const Complex& c2){
Complex c3(0,0);
c3.real = real + c2.real;
c3.imag = imag + c2.imag;
return c3;
}
};
int main(){
Complex c1(2,4), c2(3,5);
Complex c3 = c1 + c2;
c1.print();
c2.print();
c3.print();
return 0;
}
Runtime polymorphism, also called dynamic polymorphism, is resolved during runtime and is achieved through method overriding and virtual functions. It is also called dyanamic binding or late binding, as the names can be associated with the classes during runtime.
Method overriding is defined as the redefinition of a base-class method in its derived class with the same signature, i.e., the same return type and parameters.
class Base {
public:
void print(){
cout << "This is Base Class" << endl;
}
};
class Derived : public Base {
public:
void print(){
cout << "This is Derived Class" << endl;
}
};
int main(){
Derived ob;
ob.print();
// Access base class method :
ob.Base::print();
return 0;
}
The keyword virtual
represents that method being overridden. A virtual function is a member function of a class, and it can be overridden in its derived class. Virtual functions cannot be static.
class Base {
public:
// Virtual Function :
virtual void print(){
cout << "This is Base Class - Virtual" << endl;
}
// Non-Virtual Function :
void printN(){
cout << "This is Base Class - Non Virtual" << endl;
}
};
class Derived : public Base {
public:
void print(){
cout << "This is Derived Class - Virtual" << endl;
}
void printN(){
cout << "This is Derived Class - Non Virtual" << endl;
}
};
int main(){
Derived d;
Base *bptr = &d;
// Virtual function, binded at runtime :
bptr->print();
// Non-virtual function, binded at compile time :
bptr->printN();
return 0;
}
In C++, the override
identifier is used to explicitly indicate that a virtual function in a derived class is intended to override a virtual function with the same name and signature in its base class.
class Shape {
public:
virtual void draw(){
cout<<"Can not draw an unknown Shape!" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "Drawing Rectangle..." << endl;
}
};
int main(){
Rectangle rect;
rect.draw();
return 0;
}
An abstract class is a class that cannot be instantiated but can be inherited to provide an interface or blueprint for other classes. An abstract class contains at least one pure virtual function. A pure virtual function (or abstract function) is one that can be overridden in the derived class but cannot be defined in its base class, as there is no meaningful definition you could give for the function in the base class. A virtual function can be declared "pure" by using the operator =0
at the end, indicating that it has no implementation and must be overridden by any class that inherits from it.
Any class that implements an abstract class must provide an implementation for all of the pure virtual functions declared in it. If the pure virtual function is not defined in its derived class, then the derived class also becomes an abstract class. Abstract classes can have both abstract and non-abstract methods. The non-abstract methods have a default implementation in the abstract class and can be used by the subclasses as is, or overridden if necessary.
// Abstract Class :
class Shape {
public:
// Non-Abstract Function :
void print(){
cout << "Inherating shape class..." << endl;
}
// Virtual Function :
virtual void draw(){
cout << "Drawing shape..." << endl;
}
// Pure Virtual Function :
virtual void area() = 0;
};
class Rectangle : public Shape {
private:
int length, breadth;
public:
Rectangle(int l, int b){
length = l;
breadth = b;
}
void draw(){
cout << "Drawing rectangle..." << endl;
}
void area(){
cout << "Area of rectangle is " << length*breadth << endl;
}
};
int main(){
Rectangle r1(3,8);
r1.print();
r1.draw();
r1.area();
return 0;
}
An interface in object-oriented programming is a collection of abstract methods (methods without implementation) and constant variables. It provides a common set of methods that can be implemented by multiple classes. In C++, an interface is an abstract class that has only pure virtual functions.
// Interface Class :
class Shape {
public:
// Pure virtual function :
virtual void draw() = 0;
virtual float area() = 0;
};
class Rectangle : public Shape {
private:
int length, breadth;
public:
Rectangle(int l, int b){
length = l;
breadth = b;
}
void draw(){
cout << "Drawing Rectangle..." << endl;
}
float area(){
return length*breadth;
}
};
class Circle : public Shape {
private:
int radius;
public:
Circle(int r){
radius = r;
}
void draw(){
cout << "Drawing Circle..." << endl;
}
float area(){
return 3.14*radius*radius;
}
};
int main(){
// Rectangle:
Rectangle r1(3,8);
r1.draw();
cout << "Area of rectangle is " << r1.area() << endl;
// Circle:
Circle c1(4);
c1.draw();
cout << "Area of circle is " << c1.area() << endl;
return 0;
}
Abstraction is a feature of OOP; it shows only the necessary details to the user by hiding the actual implementation. Abstraction in C++ is achieved through classes, header files, and access specifiers. It is implemented by using abstract classes and interfaces. In abstraction, problems are solved at the design or interface level. It avoids code duplication and increases code reusability. In a nutshell, abstraction hides implementation with the help of abstract classes and interfaces.
class Employee {
private:
int ctc; // in LPA
public:
virtual string domain() = 0;
void setCTC(int ctc){
this->ctc = ctc;
}
int getCTC(){
return ctc;
}
void employeeInfo(){
cout << "Employee Domain: " << this->domain() << endl;
cout << "Employee CTC: " << this->getCTC() << " LPA" << endl;
}
};
class Sofware : public Employee {
public:
string domain(){
return "Sofware Development";
}
};
class Marketting : public Employee {
public:
string domain(){
return "Marketting";
}
};
int main(){
// Software :
Sofware eng;
eng.setCTC(18);
eng.employeeInfo();
// Marketting :
Marketting mrk;
mrk.setCTC(15);
mrk.employeeInfo();
return 0;
}
The wrapping or binding of fields (state) and methods (behaviour) together into a single unit is called encapsulation. This keeps data safe from outside interference and misuse. Encapsulation means restricting direct access to certain components of an object so that users can’t access the state values for all variables and helps in data hiding. Encapsulation is implemented using an access modifier, i.e., private, protected, and public. During encapsulation, problems are solved at the implementation level. In a nutshell, encapsulation is hiding the data with the help of getter and setter.
In this program, the variable salary is made private so that it can be accessed and manipulated only by using the getter and setter methods that are present within the class. Therefore, we can say that the variable salary and the getter as well as setter methods have been bound together, which is nothing but encapsulation.
class Employee {
private:
int salary;
public:
// Setter :
void setSalary(int sal){
salary = sal;
}
// Getter :
int getSalary(){
return salary;
}
};
int main(){
Employee emp;
emp.setSalary(80000);
cout << "Salary is " << emp.getSalary() << endl;
return 0;
}
An exception is an error that arises during the execution of a program. Exception handling is the process of handling errors at runtime so that the normal flow of a program can be maintained. C++ exception handling is built upon three keywords: try
, catch
, and throw
.
try
: a try block is used to place code that may result in an exception.catch
: a catch block is used to handle the exception.throw
: throw keyword throws an exception.try {
// Block of code to try
} catch(Exceptions) {
// Block of code to handle errors
}
try {
float x=5, y=0;
if (y == 0)
throw "Error: Division By Zero!";
else
cout << "Division is" << x/y;
} catch(const char *E) {
cout << E << endl;
}
try {
int age = 16;
if (age >= 18)
cout << "Access Granted" << endl;
else
throw 404;
} catch (...) {
cout << "Access Denied! You must be at least 18 years old." << endl;
}
try {
int age;
cout << "Enter Age: ";
cin >> age;
if (age == 0)
throw "Error: Age cannot be zero!";
else if (age < 0)
throw std::runtime_error("Runtime Error: Age cannot be negative!");
else
cout << "Your age is " << age << endl;
} catch (const char *E){
cout << E << endl;
} catch (std::runtime_error& E){
cout << E.what() << endl;
} catch (...){
cout << "Unkwown Error!" << endl;
}
The new exception can be defined by overriding and inheriting exception class functionality.
// User-Defined Error Class :
class ZeroDivisionError : public exception {
public:
const char* what() const throw () {
return "Error: Attempted to divide by zero!";
}
};
int main(){
try {
int x, y;
cout << "Enter Two Numbers: ";
cin >> x >> y;
if (y == 0){
throw ZeroDivisionError();
}
else
cout << "Division is " << (float)x/y << endl;
} catch (ZeroDivisionError& E){
cout << E.what() << endl;
}
return 0;
}
A standard C++ library called fstream is used to read and write from a file.
Class | Description |
---|---|
ifstream |
Reads from files |
ofstream |
Creates and writes to files |
fstream |
Creates, reads, and writes to files |
#include<iostream>
#include<fstream>
using namespace std;
int main(){
// Creating object of ifstream class:
ifstream infile;
// Opening file to read:
infile.open("sample.txt",ios::in);
// Reading file:
string text;
while(getline(infile,text))
cout << text << endl;
return 0;
}
Mode Flag | Description |
---|---|
ios::app |
Append mode. All output to that file to be appended to the end |
ios::ate |
Open a file for output and move the read/write control to the end of the file |
ios::in |
Open a file for reading |
ios::out |
Open a file for writing |
ios::trunc |
If the file already exists, its contents will be truncated before opening the file |
#include<iostream>
#include<fstream>
using namespace std;
int main(){
// Crearing file:
ofstream outfile("sample.txt");
// Write to the file:
outfile << "I am learning C++\n";
outfile << "C++ is the fast and efficient language.";
// Closing file:
outfile.close();
return 0;
}
#include<iostream>
#include<fstream>
using namespace std;
int main(){
string fname;
char lname[20];
// User Input:
cout << "Enter First Name: ";
getline(cin,fname); // Receive string
cout << "Enter Last Name: ";
cin.getline(lname, 20); // Receive char array
// Writing file:
ofstream outfile;
outfile.open("name.txt");
outfile << fname+" "+lname;
outfile.close();
// Reading file:
ifstream infile;
infile.open("name.txt");
string line;
while(getline(infile,line))
cout << line << endl;
infile.close();
return 0;
}
It is a pre-defined function defined in the <string.h>
header file that is used to accept a line or a string from the input stream until the delimiting character is encountered. The cin is an object that is used to take input from the user but does not allow the user to take the input in multiple lines. To accept the multiple lines, we use the getline()
function.
#include<iostream>
#include<fstream>
using namespace std;
int main(){
string name;
cout << "Enter Full Name: ";
cin >> name;
cout << name << endl;
cin.ignore();
cout << "Enter : ";
getline(cin, name);
cout << name << endl;
return 0;
}
Memory allocated during runtime is called dynamic memory, and the process of allocating memory at the time of execution is called dynamic memory allocation. C++ allows us to allocate the memory at run time. This is known as dynamic memory allocation. In C++, the memory is allocated and then deallocated dynamically using the new
and delete
operators.
The new
operator allocates memory to a variable. The new operator returns the address of the memory location, and it is stored in pointer.
pointer_var = new data_type;
The delete
operator is used to deallocate the memory taken by the new operator. It returns the memory to the operating system. This is known as memory deallocation.
delete pointer_var;
// Addition of two integers using dyanamic memory:
int *p_a, *p_b;
p_a = new int;
p_b = new int;
cout << "Enter Two Numbers: ";
cin >> *p_a >> *p_b;
cout << "Addition is " << *p_a+*p_b << endl;
delete p_a, p_b;
// Addition of 5 integers (array) using dyanamic memory:
int sum = 0;
int *p_arr;
p_arr = new int[5];
cout << "Enter 5 Numbers: ";
for(int i=0; i<5; i++){
cin >> *(p_arr+i);
sum += *(p_arr+i);
}
cout << "Addition is " << sum << endl;
delete[] p_arr;
class Sum {
public:
int a, b;
Sum(int a, int b){
this->a = a;
this->b = b;
}
void sum(){
cout << "Addition is " << a+b << endl;
}
};
int main(){
Sum *p_sm = new Sum(22,17);
p_sm->sum();
delete p_sm;
return 0;
}
Templates are the foundation of generic programming, which involves writing code in a way that is independent of any particular type. A template is a blueprint or formula for creating a generic class or function. The library containers like iterators and algorithms are examples of generic programming and have been developed using the template concept.
Generic functions use the concept of a function template. Generic functions define a set of operations that can be applied to various types of data. The type of data that the function will operate on depends on the type of data passed as a parameter. A generic function is created by using the keyword template
.
The type is only a placeholder for the data type, which the compiler will automatically replace with the actual data type. It is used within the function definition. And typename
is a keyword.
template <typename type>
return_type functionName(parameters_list){
// body of function
}
// Function Template:
template <typename T>
T maxn(T a, T b){
return a > b ? a : b;
}
int main(){
cout << maxn(2,4) << endl; // for int:
cout << maxn<int>(4,8) << endl;
cout << maxn(5.5,4.25) << endl; // for float:
cout << maxn("hello","world") << endl; // for string:
return 0;
}
template <typename T1, typename T2>
float add(T1 a, T2 b){
return a+b;
}
int main(){
cout << add(2,4) << endl; // for int
cout << add(20.25,10) << endl; // for float & int
return 0;
}
template <typename T1, typename T2>
float add(T1 a, T2 b){
return a+b;
}
template <typename T1, typename T2, typename T3>
float add(T1 a, T2 b, T3 c){
return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
}
int main(){
cout << add(2,4) << endl;
cout << add(20.25,10) << endl;
cout << add(2,4,6) << endl;
cout << add(10,12.5,12) << endl;
return 0;
}
When a class uses the concept of a template, then the class is known as a generic class. A class template starts with the keyword template
, followed by the template parameter(s) inside <>
, which is followed by the class declaration.
template <typename type>
class ClassName {
// Class Definition
}
// Class Template:
template <typename T>
class Generic {
private:
T num1, num2;
public:
Generic(T n1, T n2){
num1 = n1;
num2 = n2;
}
T add(){
return num1+num2;
}
};
int main(){
Generic<int> obi(2,4);
cout << obi.add() << endl;
Generic<float> obf(2.5,4.5);
cout << obf.add() << endl;
return 0;
}
template <typename T1, typename T2>
class Generic {
private:
T1 num1;
T2 num2;
public:
Generic(T1 n1, T2 n2){
num1 = n1;
num2 = n2;
}
float add(){
return num1+num2;
}
};
int main(){
Generic<int,int> ob(2,4);
cout << ob.add() << endl;
Generic<float,int> ob2(2.5,2);
cout << ob2.add() << endl;
return 0;
}
A namespace is a collection of related names or identifiers (such as variables, functions, classes, etc.) under a single name. It helps to separate identifiers with the same name in other namespaces or the global namespace. A namespace defines a scope. A namespace definition begins with the keyword namespace
, followed by the namespace name. To call the namespace-enabled version of either function or variable, prepend the scope resolution operator (::
) and the namespace name. Namespaces can be nested.
#include<iostream>
using namespace std;
// Namespace integers :
namespace integers {
int add(int a, int b){
return a+b;
}
}
// Namespace floats :
namespace floats {
float add(float a, float b){
return a+b;
}
}
int main(){
// Integer addition:
cout << integers::add(5,10) << endl;
// Float addition:
cout << floats::add(5.20,15.25) << endl;
return 0;
}
The prepending of namespaces can be avoided by the using
namespace directive. This directive tells the compiler that the subsequent code is making use of names in the specified namespace.
#include<iostream>>
using namespace std;
namespace morning {
void greet(){
cout << "Good Morning!" << endl;
}
}
namespace evening {
void greet(){
cout << "Good Evening!" << endl;
}
}
using namespace morning;
int main(){
greet();
return 0;
}
A namespace can be defined in several parts, and a namespace is made up of the sum of its separately defined parts. The separate parts of a namespace can be spread over multiple files. The following namespace definition either defines a new namespace or adds new elements to an existing one.
namespace integers {
int subtract(int a, int b){
return a-b;
}
}
The preprocessors are the directives, which give instructions to the compiler to preprocess the information before actual compilation starts. The preprocessor directives are preceded by a hash sign (#
), and no semicolon (;
) is expected at the end of a preprocessor directive as it is not a program statement.
A macro is a piece of code that is defined using the #define
directive, and it is replaced with its corresponding value at compile time. The #define
directive is used to define the preprocessor macro by creating symbolic constants, and the #undef
directive is used to undefine the macro.
// Define Macro :
#define identifier replacement
// Undefine Macro :
#undef identifier
#include<iostream>
using namespace std;
// Define macro :
#define PI 3.14159
#define NEWLINE '\n'
#define MAX(a,b) (a > b ? a : b)
int main(){
cout << "Value of Pi = " << PI << NEWLINE;
cout << "Max NO = " << MAX(10,25) << NEWLINE;
return 0;
}
Macro | Description |
---|---|
__LINE__ |
current line number of program when it is being compiled |
__FILE__ |
current file name of program when it is being compiled |
__DATE__ |
date of the translation of source file into object code as a string (format: month day year) |
__TIME__ |
time at which program was compiled as a string (format: hh:mm:ss) |
cout << "Line : " << __LINE__ << endl;
cout << "FILE : " << __FILE__ << endl;
cout << "DATE : " << __DATE__ << endl;
cout << "TIME : " << __TIME__ << endl;
A file inclusion directive (#include
) is a preprocessor directive that tells the compiler to include the contents of another file in the source code program. There are two types of files that can be included by the user in the program:
Header Files or Standard Library : These files contain definitions of pre-defined functions that are built into the C++ language.
#include <file_name>
User-Defined Files : When a program becomes very large and complex, it is a good practice to divide it into smaller files and include them whenever needed. These types of files are user-defined files.
#include "file_name"
Directive | Description |
---|---|
#ifdef MACRO |
check whether MACRO is defined by #define or not |
#ifndef MACRO |
check whether MACRO is not defined by #define |
#endif |
terminate macro condition |
#if [condition] |
check whether condition is true (similar to if statement) |
#else |
code to execute when condition is false |
#elif [condition] |
similar to else-if statement |
#ifdef MACRO
// true_if_macro_defined
#endif
#define PI 3.14159
#ifdef PI
#undef PI
#endif
int main(){
// this will throw an error as PI is undefined
cout << "Value of PI is " << PI << endl;
return 0;
}
#ifndef PI
#define PI 3.14159
#endif
int main(){
cout << "Value of PI is " << PI << endl;
return 0;
}
#define NUM 10
#if NUM == 10
#undef NUM
#define NUM 20
#endif
int main(){
cout << NUM << endl;
return 0;
}
#define NUM 10
#if NUM == 5
#undef NUM
#define NUM 10
#elif NUM == 10
#undef NUM
#define NUM 15
#endif
int main(){
cout << NUM << endl;
return 0;
}
#ifdef NUM
#undef NUM
#define NUM 10
#else
#define NUM 15
#endif
int main(){
cout << NUM << endl;
return 0;
}