Nilesh Pabuwal
Nilesh Pabuwal
Nilesh Pabuwal
Nilesh Pabuwal
Index
• Chapter 1, Your first C++ Application, will equip you with the fundamental tools and techniques required to get started building basic C++
applications.
• Chapter 2, Built-in Data Types, vectors and arrays. These are then utilized in the creation of a real-world sign-up application.
• Chapter 3, Control Flow
• Chapter 4, Operators, presents a variety of operators provided by C++, describing what they do and how they can allow us to manipulate our
data.
• Chapter 5, Pointers and References
• Chapter 6, Dynamic Variables, introduces dynamic variables ,their ownership and Lifetime – that is, variables that can be created when needed
and can hold an arbitrarily large amount of data that is limited only by the memory that is available.
• Chapter 7, Classes and Structs, presents the fundamentals of structs and classes.
• Chapter 8, Object-Oriented Principles, presents best practices for designing classes and will give you an overview of abstraction and
encapsulation, where to use them.
• Chapter 9, Advanced Object-Oriented Principles, presents a number of advanced object-oriented principles, including inheritance and
polymorphism, that will allow us to build more dynamic and powerful C++ applications.
• Chapter 10, Templates, covers an overview of templates and gives some examples of how they can be used.
• Chapter 11, Containers and Iterators.
• Chapter 12, Exception Handling
In parallel – Students would be working on Real-Time case based on their family business and try to convert and create Project.
Chapter 1, Your first C++ Application, will equip you
with the fundamental tools and techniques required
to get started building basic C++ applications.
Why C++ , Advantages
• Performance: By putting the programmer close to the hardware, C++ allows us to write
very efficient programs. Along with low-level memory access, the abstraction between
code and what the machine will do is smaller than in most other languages, meaning
you can manipulate the system better.
• Portability: C++ can be cross-compiled to a wide array of platforms, and runs on
everything from watches to televisions. If you're writing an application or library for
more than one platform.
• General purpose: C++ is a general-purpose programming language, and is used in
everything from video games to enterprise. With a rich feature set spanning everything
from direct memory management to classes and other Object-Oriented Programming
(OOP) principles, you can make C++ work for you.
• Large libraries: Since the language is used in so many applications, there's an
abundance of libraries to choose from. With hundreds of open source repositories, the
wealth of information (and the support systems that come with it) is vast.
Online Editors
• Tutorialspoint C++ compiler: https://www.tutorialspoint.com/compile_cpp_online.php.
• cpp.sh: This website allows you to pick a C++ language version and warning level, and compile a
single file. However, it does not print error messages from the operating system. You can find it
at http://cpp.sh/.
• godbolt compiler explorer: This website allows you to compile a single file on many different
compilers and shows the output assembly language; its UI is a little subtle for some tastes. It
prints error messages from the operating system. You can find it at https://godbolt.org/.
• coliru: This website allows you to compile a single file. It prints error messages from the operating
system. You can find it at http://coliru.stacked-crooked.com/.
• repl.it: This website allows you to compile multiple files. You can find it
at https://repl.it/languages/cpp.
• Rextester: This website lets you compile a single file using Microsoft Visual C++. You can find it
at https://rextester.com/.
• Visual Studio Editor
C++ Build Pipeline
#include <iostream>
int main()
{
std::cout << "Hello World!";
return 0;
}
Anatomy of a C++ Application
• Starting from the top, we have a preprocessor directive:
#include <iostream>
• Preprocessor directives are statements that allow us to perform
certain operations before the program is built.
• The include directive is a very common directive that you'll see in
most C++ files, and it means "copy here." So, in this case, we're going
to copy the contents of the iostream header file into our application,
and in doing so, allow ourselves to use input/output functionality it
provides.
Anatomy of a C++ Application
• Next, we have our entry point, main():
int main()
The main() function is where your C++ application will kick-off. All applications will have this function defined
and it marks the start of our application—the first code that will be run. This is typically your outer-most loop
because as soon as the code in this function is complete, your application will close.
• Next, we have an IO statement that will output some text to the console:
std::cout << "Hello World!";
Because we have included the iostream header at the start of our application, we have access to various input
and output functionality. In this case, std::cout. cout allows us to send text to the console, so when we run our
application, we see that the text "Hello World!" is printed. We'll cover data types in more detail in the coming
chapters.
•unsigned: The unsigned keyword specifies that our variable should only hold positive values. This increases the upper
range of the variable but decreases its lower range as it's capped at 0.
•long: The long keyword ensures that our variable will be at least the size of an int; typically, this will be 4 bytes. This will,
in some cases, increase the range of the value that can be stored.
•long long (C++11): The long long keyword, added in C++11, ensures that our variable will be greater in size than long;
typically, this will be 8 bytes. This will, in most cases, increase the range of the value that can be stored.
•short: The short keyword ensures that our variable has the smallest memory footprint it can, whilst ensuring a size less
than long; typically, this will be 4 bytes.
Note
The exact size of data types depends on factors such as the architecture that you're working with and what compiler flags are set, though
typical sizes will be shown in a reference chart shortly. It's important to note that the C++ standard does not guarantee absolute sizes for
types but minimum ranges that they must be able to store. This then means that modified types may also differ between platforms.
Built-In Types
•bool: The bool type stores either a true (non-zero) or false (0) value and has
a size of one byte.
•int: The int type is used to store integers and is typically four bytes in size.
•char: The char type is used to store a single character. This is stored in the
form of an integer and gets resolved into a character depending on which
character set is used, typically ASCII. This data type is one byte in size.
•void: The void type is a special type that denotes an empty value. You
cannot create objects of the void type. However, it can be used by pointers
and functions to denote an empty value—for example, a void pointer that
points to nothing, or a void function that doesn't return anything.
•wide character: The wchar_t type is used to store wide characters (Unicode
UTF-16). The size of wchar_t is compiler-specific, although C++11 introduced
the fixed size types, char16_t and char32_t.
Inputs From Keyboard For different Data Types
#include <iostream>
using namespace std;
#include <iostream>
#include <string> int main() {
using namespace std; char *p = new char[1024]; // allocate memory
cin >> p; //forexample: haha
int main() char* q = p;
{ cout << "&q = " << &q << endl;
string name; cout << "q = " << q << endl;
cout << "Enter your name: "; return 0;
cin>>name; }
getline(cin, name); // To read a line with spaces
cout << name; #include<iostream>
return 0; using namespace std;
} int main()
{
char myChar = 'a’;
int ASCII = myChar;
for(int i=0;i<255;i++)
{
cout<<char(i)<<i<<'\t’;
}
return 0;
}
Declaring Variable and Checking its Size
#include<iostream>
using namespace std;
int main()
{
int myInt = 1;
bool myBool = false;
char myChar = 'a’;
float myfloat=3.4;
std::cout << "The size of an int is " << sizeof(myInt) << ".\n";
std::cout << "The size of a bool is " << sizeof(myBool) << ".\n";
std::cout << "The size of a char is " << sizeof(myChar) << ".\n";
std::cout << "The size of a char is " << sizeof(myfloat) << ".\n";
return 0;
}
Converting Values from int, float, string
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <cstdlib> // for atoi function #include <sstream> // for stringstream
using namespace std; using namespace std;
int main() {
string str = "123.456";
float fnum = stof(str);
cout << "Converted float: " << fnum << endl;
return 0;
}
Containers - Array
Multidimensional - Array
// Struct example.
#include <iostream>
#include <string>
struct Coordinate
{
float x = 0;
float y = 0;
};
int main()
{
Coordinate myCoordinate;
myCoordinate.x = 1;
myCoordinate.y = 2;
std::cout << "Coordinate: " << myCoordinate.x << ", " << myCoordinate.y;
}
•Classes and structs encapsulate variables and behaviors.
Classes •Class members are private by default, whereas they're
public in a struct.
A class is a collection of variables and functionality, encapsulated neatly
•We can modify the visibility of our members with access
within a single object. When we define a class, we're creating a
modifiers.
blueprint for that object. This means that every time we want to create •Constructors and destructors can be used to call code at
an object of that type, we use that blueprint to construct our object. each end of an object's lifetime.
// Class example. Members (variables and functions) declared in a C++ class are,
#include <iostream>
#include <string>
by default, private. This means that they're only accessible to
class MyClass the class itself, so cannot be accessed by external classes. This
{ can be changed, however, through the use of access modifiers;
private: // Any members declared from this point forth will be private. we'll cover these shortly. Classes can also inherit from one
int myInt = 0;
public: another,
void IncrementInt()
{ •Public—Any members declared public are accessible from
myInt++; anywhere the class is.
std::cout << "MyClass::IncrementInt: " << myInt;
};
•Private—Any members declared private are only available to the
protected:// Any members declared from this point forth will be protected. class in which they're defined and to friend functions.
•Protected—Protected members are similar to private members,
}; with the addition that child classes can access them.
int main()
{ Note
MyClass classObject; Child classes are those that inherit from a base class. This will be
classObject.IncrementInt(); covered in detail in Chapter 10, Advanced Object-Oriented
}
Principles.
Exercise
// Accessibility example. #include <iostream>
#include <iostream> #include <string>
#include <string> class MyClass
class MyClass {
{ public:
public: MyClass()
int myPublicInt = 0; {
protected: std::cout << "My Class Constructor Called\n";
int myProtectedInt = 0; myPublicInt = 5;
private: }
int myPrivateInt = 0; ~MyClass()
}; {
std::cout << "My Class Destructor Called\n";
int main() }
{ int myPublicInt = 0;
MyClass testClass; };
std::cout << testClass.myPublicInt << "\n"; int main()
std::cout << testClass.myProtectedInt << "\n"; {
std::cout << testClass.myPrivateInt << "\n"; std::cout << "Application started\n";
} MyClass testClass;
std::cout << testClass.myPublicInt << "\n";
// Classes/struct exercise. int main()
#include <iostream> {
#include <string> MyClass classObject;
class MyClass
{ std::cout << "classObject::myInt: " << classObject.myInt << "\n";
public: std::cout << "classObject::myBool: " << classObject.myBool << "\n";
int myInt = 0; std::cout << "classObject::GetString: " << classObject.GetString() << "\n";
bool myBool = false;
std::string GetString() MyStruct structObject;
{
return "Hello World!"; std::cout << "\nstructObject::myInt: " << structObject.myInt << "\n";
} std::cout << "structObject::myBool: " << structObject.myBool << "\n";
}; std::cout << "structbject::GetString: " << structObject.GetString() << "\n";
struct MyStruct }
{
int myInt = 0;
int myBool = 0;
std::string GetString()
{
return "Hello World!";
}
};
Storage Life time
#include <iostream> #include <iostream> // Static example.
void MyFunc() #include <string> #include <iostream>
{ int MyInt() #include <string>
int myInt1 = 1; { int MyInt()
} int myInt = 0; {
int main() return ++myInt; static int myInt = 0;
{ } return ++myInt;
int myInt2 = 2; int main() }
{ { int main()
int myInt3 = 3; for (int i = 0; i < 5; ++i) {
} { for (int i = 0; i < 5; ++i)
// print values std::cout << MyInt(); {
std::cout << myInt1 << std::endl; } std::cout << MyInt();
std::cout << myInt2 << std::endl; } }
std::cout << myInt3 << std::endl; }
}
switch (std::stoi(inputString))
Practical Exercise {
case 1:
{
// Activity 3: SignUp Application. int main() std::string name = "";
#include <iostream> { int age = 0;
std::cout << "User SignUp Application\n" << std::endl; std::cout << "\nAdd User. Please enter user name and age:\n";
#include <string> std::cout << "Name: ";
bool bIsRunning = true;
#include <vector> while (bIsRunning)
std::getline(std::cin, name);
std::cout << "Age: ";
#include <stdexcept> { std::getline(std::cin, inputString);
struct Person std::cout << "Please select an option:\n"; age = std::stoi(inputString);
{ std::cout << "1: Add Record\n"; AddRecord(name, age);
}
int age = 0; std::cout << "2: Fetch Record\n";
break;
std::cout << "3: Quit\n\n";
std::string name = ""; case 2:
std::cout << "Enter option: "; {
}; std::string inputString; int userID = 0;
std::vector<Person> records; std::getline(std::cin, inputString); std::cout << "\nPlease enter user ID:\n";
void AddRecord(std::string newName, int std::cout << "User ID: ";
//Determine user selection.
std::getline(std::cin, inputString);
newAge) userID = std::stoi(inputString);
{ Person person;
try
Person newRecord; {
newRecord.name = newName; person = FetchRecord(userID);
newRecord.age = newAge; }
catch (const std::out_of_range& oor)
records.push_back(newRecord); {
std::cout << "\nUser record added std::cout << "\nError: Invalid UserID.\n\n";
break;
successfully.\n\n"; }
}; std::cout << "User Name: " << person.name << "\n";
Person FetchRecord(int userID) std::cout << "User Age: " << person.age << "\n\n";
}
{ break;
return records.at(userID); case 3:
bIsRunning = false;
}; break;
default:
std::cout << "\n\nError: Invalid option selection.\n\n";
break;
}
} }
Chapter 3: Control Flow
If – Else – Syntex
if (condition) { //Chained if-else (using else if)
// Code to execute if condition is true if (condition1) {
} // Code to execute if condition1 is true
} else if (condition2) {
if (condition) { // Code to execute if condition1 is false and condition2 is true
// Code to execute if condition is true } else {
} else { // Code to execute if both conditions are false
// Code to execute if condition is false }
}
//else if - Multiple Conditions
//Nested if – Else if (condition1 && condition2) {
if (condition1) { // Code to execute if both condition1 and condition2 are true
if (condition2) { } else if (condition3 || condition4) {
// Code to execute if both conditions are true // Code to execute if either condition3 is true or condition4 is
} else { true
// Code to execute if condition2 is false } else {
} // Code to execute if none of the above conditions are true
} else { }
// Code to execute if condition1 is false
} //Ternary Operator:
variable = (condition) ? expression1 : expression2;
Switch Case
switch (expression) { //Multiple Case
case value1: switch (expression) {
// Code to execute if expression equals value1 case value1:
break; case value2:
case value2: // Code to execute if expression equals either value1 or
// Code to execute if expression equals value2 value2
break; break;
// ... additional cases // ... additional cases
default: }
// Code to execute if expression doesn't match any case
} // No break means control will fall through behaviour
switch (expression) {
//Switch with Initialization case value1:
switch (int var = some_function(); var) { // Code for value1
case 1: break;
// ... case value2:
break; // Code for value2
// ... other cases case value3:
} // Code for value3 (will execute if value2 is matched)
break;
// ... additional cases
}
//Enumeration in Switch
//Test for Ternary Conditional Operation
int a = 5;
enum Days { MON, TUE, WED, THU, FRI, SAT, SUN };
int b = 10;
int max = (a > b) ? a : b;
Days today = MON;
switch (today) {
case MON: #include<iostream>
// ... #include<string>
break; using namespace std;
// ... other cases int main()
} {
int main() {
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
std::cout << "(" << i << ", " << j << ") ";
return 0;
}
Chapter 4: Operators, presents a variety of
operators provided by C++, describing what they do
and how they can allow us to manipulate our data.
Arithmetic Operators
// Arithmetic operators. // Prime number checker.
#include <iostream> #include <iostream>
#include <string>
#include <string> int main()
int main() {
{ int numberToCheck = 0;
std::cout << "Prime number checker\n";
int addition = 3 + 4;
std::cout << "Enter the number you want to check: ";
int subtraction = 5 - 2; std::cin >> numberToCheck;
int division = 8 / 4; if (numberToCheck <= 1)
int multiplication = 3 * 4; {
std::cout << numberToCheck << " is not prime.";
std::cout << addition << "\n"; return 0;
std::cout << subtraction << "\n"; }
std::cout << division << "\n"; else if (numberToCheck == 2)
{
std::cout << multiplication << "\n";
std::cout << numberToCheck << " is prime.";
} return 0;
}
// Arithmetic operators – Modulus for (int i = 2; i < numberToCheck; ++i)
#include <iostream> {
#include <string> if (numberToCheck % i == 0)
{
int main() std::cout << numberToCheck << " is not prime.";
{ return 0;
int modulus = 11 % 2; }
std::cout << modulus << "\n"; }
std::cout << numberToCheck << " is prime.";
} }
Relational Operators //Block 2
if (time < 0000 || time > 2400)
{
std::cout << "Invalid time.";
return 0;
}
if (time == 0000)
{
//Block 1
std::cout << "It's currently midnight.";
// Time of Day Calculator. }
#include <iostream> else if (time == 1200)
#include <string> {
std::cout << "It's currently noon.";
int main() }
{ else if (time >= 0600 && time < 1200)
std::cout << "***Time of Day Calculator***\n"; {
std::cout << "It's currently morning.";
std::cout << "Enter time in military format. eg. (1800, 1430)\n\n";
}
std::cout << "Enter time: "; else if (time > 1200 && time <= 1700)
std::string input; {
getline(std::cin, input); std::cout << "It's currently afternoon.";
}
int time = std::stoi(input); else if (time > 1700 && time <= 2000)
{
std::cout << "It's currently evening.";
}
else if (time > 2000 || time < 0600)
{
std::cout << "It's currently night.";
}
}
Unary Operators
// Increment/Decrement example. So far, the operators that we've used had a value, typically called an operand, on
#include <iostream> either side of them: rhs and lhs. Unary operators are those operators, however, that
#include <string> take only one value and modify that. We'll be taking a quick look at minus (-),
int main() increment (++), and decrement (--). There are a number of other unary operators
{ (logical complement (!) and bitwise complement (~))
int myInt = 1;
std::cout << ++myInt << std::endl; // Pre/Post Increment Example.
std::cout << --myInt << std::endl; #include <iostream>
} #include <string>
int main()
// Negation example. {
#include <iostream> int myInt = 5;
#include <string> std::cout << ++myInt << std::endl;
int main() std::cout << myInt << std::endl;
{ myInt = 5;
int myInt = -1; std::cout << myInt++ << std::endl;
std::cout << -myInt * 5 << std::endl; std::cout << myInt << std::endl;
myInt = 1; }
std::cout << -myInt * 5 << std::endl;
}
Assignment Operators
// Assignment Operators Example.
#include <iostream>
#include <string>
int main()
{
int myInt = 5;
myInt += 5;
std::cout << myInt << std::endl;
myInt -= 5;
std::cout << myInt << std::endl;
myInt *= 5;
std::cout << myInt << std::endl;
myInt /= 5;
std::cout << myInt << std::endl;
myInt %= 5;
std::cout << myInt << std::endl;
}
Logical Operators
•AND (&&): This returns true when both conditions are true, and false otherwise.
•OR (||): This returns true when either condition is true, and false otherwise.
•NOT (!): This returns true if the condition is false, and true otherwise; essentially, it returns the opposite of the
condition.
class Point {
private:
int x, y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) {}
int main() {
Point p(2, 3);
std::cout << p << std::endl; // Using overloaded <<
return 0;
}
Overloading the = Operator for a Custom Class
class Point {
private:
int x, y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) {}
Point& operator=(const Point& p) {
x = p.x;
y = p.y;
return *this;
}
void display() {
std::cout << "x: " << x << ", y: " << y << std::endl;
}
};
int main() {
Point p1(2, 3), p2;
p2 = p1; // Using overloaded =
p2.display();
return 0;
}
Bitwise AND (&): Takes two numbers as operands and Left Shift (<<): Shifts the bits of the number to the left by the
does AND on every bit of two numbers. specified number of positions.
int a = 5; // 0101 in binary
int a = 5; // 0101 in binary
int b = 3; // 0011 in binary
int result = a << 2; // 10100 in binary, which is 20 in decimal
int result = a & b; // 0001 in binary, which is 1 in decimal
Right Shift (>>): Shifts the bits of the number to the right by
Bitwise OR (|): Takes two numbers as operands and does
the specified number of positions.
OR on every bit of two numbers.
int a = 5; // 0101 in binary int a = 20; // 10100 in binary
int b = 3; // 0011 in binary int result = a >> 2; // 00101 in binary, which is 5 in decimal
int result = a | b; // 0111 in binary, which is 7 in decimal
void *ptrVoid;
int a = 10;
ptrVoid = &a; // Can point to any data type but requires explicit
typecasting before dereferencing
References
#include <iostream> #include <iostream> int arr[5];
using namespace std; using namespace std; int (&refToArray)[5] = arr;
int main() void copychars(char* from, char* to, int count)
{ { struct MyStruct {
int i = 10; if (from == nullptr || to == nullptr) int x;
int & ir = i; return; float y;
i = i + 10; while (count-- > 0) };
ir = ir * 10; { MyStruct s;
cout << "i = " << i << endl; *to++ = *from++; MyStruct& refToStruct = s;
int *ip = & ir; }
class MyClass {
*ip = 33; }
// ...
cout << "i = " << i << ", *ip = " << * ip int main()
};
<< ", ir = " << ir << endl; {
MyClass obj;
return 0; char string[] { "uvwxyz" };
MyClass& refToObj = obj;
} char buffer[10];
copychars (string, buffer, 7); int* ptr = nullptr;
Bad References int main()
cout << buffer << endl; int*& refToPtr = ptr;
{
return 0;
char* p = nullptr;
} template <typename T>
char& r = *p;
void function(T& ref) {
r = '!';
enum Color { RED, GREEN, BLUE }; // ...
return 0;
Color& refToColor = RED; }
}
Difference between Pointer and Reference
Heads Pointers References
Declaration and Initialization int* ptr = &variable; int& ref = variable;
You need to explicitly use the * operator for Once initialized, it behaves like an alias to the variable it
dereferencing and the & operator to get the references, and you use it directly.
address.
Memory Address vs. Alias Contains the memory address of another Does not have its own memory address. It's simply another
variable. This means that pointers can be nullptr name for an existing variable. Therefore, you cannot have a
(or NULL in older versions) if they don't point to nullptr reference; a reference must always refer to a valid
any valid memory location. object.
Dereferencing int value = *ptr; ref = 10; // This modifies the original variable.
To access the value of the variable it points to, You directly use the reference name to access or modify the
you use the * operator. value of the referred variable.
Reassignment int anotherVariable = 20; int anotherVariable = 20;
ptr = &anotherVariable; ref = anotherVariable;
// Now ptr points to anotherVariable. // This assigns the value, doesn't change the reference itself.
Nullability Can be set to nullptr to indicate that it doesn't Always refers to a valid object and cannot be nullptr
point to any valid memory location
Deleting //Dynamic Allocation with new and int* ptr = nullptr; Dynamic Allocation with new[] and
delete delete ptr; delete[] (for arrays):
int* ptr = new int; // No effect, safe to delete int* arr = new int[10];
delete ptr; delete[] arr;
Pointers
#include <iostream>
using namespace std;
int main()
{
int i = 12345;
int *p = &i;
cout << "p = " << p << ", &i = " << &i << endl;
cout << "i = " << i << endl;
*p = *p + 2;
cout << "i = " << i << endl;
return 0; //Dereferencing nullptr
} #include <iostream>
using namespace std;
int main()
{
int *p1 = nullptr;
cout << "p1 = " << p1 << endl;
*p1 = 22;
return 0;
}
Dynamic Memory Allocations
int main() { int main() {
int *arr = new int[5]; int a = 10, b = 20, c = 30;
// Dynamically allocate memory for an array of 5 integers int *ptrArr[3] = {&a, &b, &c}; // Array of pointers
return 0;
}
#include <iostream>
Pointers and Functions // Define a function that matches the signature of our function
pointer
void printMessage(const char* message) {
void modifyValue(int *ptr) { std::cout << "Message from function: " << message <<
*ptr = 20; std::endl;
} }
return 0;
}
Pointer Arithmetic
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int main() int main()
{ {
int numbers[5] {0, 100, 200, 300, 400}; int a[5]{ 10, 20, 30, 40, 50 };
int * pint = numbers; int* p;
int * p2 = & numbers[3]; for (p = &a[0]; p < &a[5]; p = p + 1)
cout << "pint = " << pint << ", pint+1 = " << pint + 1 {
<< ", sizeof(int) = " << sizeof(int) << endl; cout << *p << " ";
cout << "*(pint+1) = " << * (pint + 1) }
<< ", pint[1] = " << pint[1] << endl; cout << endl;
cout << "*(pint+4) = " << * (pint + 4) return 0;
<< ", pint[4] = " << pint[4] << endl; }
cout << "p2 - pint = " << p2 - pint << endl;
cout << "p2 == pint = " << boolalpha << (p2 == pint) << endl;
cout << "p2 > pint = " << boolalpha << (p2 > pint) << endl;
return 0;
}
#include <iostream>
using namespace std; Pointers to Pointers
int main()
{ #include <iostream>
int a[]{ 10, 20, 30, 40, 50 }; using namespace std;
int* p; int main()
for (p = a; p < a + sizeof(a)/sizeof(a[0]); ++p) {
{ char* alphabet[26]
cout << *p << " "; {
} "alpha",
cout << endl; "bravo",
return 0; "charlie",
} "delta",
"echo",
"foxtrot"
};
for (char **p = alphabet; *p != nullptr; ++p)
{
cout << *p << " ";
}
cout << endl;
return 0;
}
#include <iostream> //Passing by Reference
#include <iostream>
int main() { void increment(int& num) {
int x = 10; num++;
int& ref = x; // Reference to x }
int main() {
ref = 20; // This changes the value of x as well int value = 5;
increment(value);
std::cout << x << std::endl; // Outputs: 20 std::cout << value << std::endl; // Outputs: 6
return 0; return 0;
} }
//Referencing a Pointer
// Referencing with Array #include <iostream>
#include <iostream> int main() {
int main() { int x = 10;
int arr[5] = {1, 2, 3, 4, 5}; int* ptr = &x;
int& thirdElement = arr[2]; int*& refToPtr = ptr; // Reference to a pointer
thirdElement = 10; // Changes arr[2] to 10 *refToPtr = 20; // Changes the value that ptr points to
std::cout << arr[2] << std::endl; // Outputs: 10 std::cout << *ptr << std::endl; // Outputs: 20
return 0; return 0;
} }
#include <iostream> #include <iostream> void myFunction(int x) {
using namespace std; using namespace std;
struct mydata struct mydata
// ...
{ { }
char const * name_;
bool hero_;
char const* name_; void (&refToFunction)(int) =
bool darkside_; myFunction;
};
mydata (char const* name, bool dark)
mydata heroes[]
{ {
{"Spider Man", true}, name_ = name; darkside_ = dark;
{"The Joker", false}, }
{"Doctor Octopus", false}, };
{"Thor", true}, mydata cast[3]
{"Batman", true}, {
{"Loki", false} { "Darth Vader", true },
}; { "Luke Skywalker", false },
void printdata(mydata * p) { "Han Solo", false }
{ };
cout << "Hello. I am " << ( * p).name_ << ". "; void printname(mydata& data)
if (p - > hero_)
{
cout << "I am a hero." << endl;
cout << "Hello. I am " << data.name_ << endl;
else
cout << "I am a villain." << endl; if (data.darkside_)
} cout << "I was seduced by the dark side" << endl;
int main() }
{ int main()
cout << sizeof(mydata) << " " << sizeof(mydata * ) << endl; {
for (mydata * p = heroes; p < heroes + 6; ++p) \ for (mydata& data : cast)
{ {
printdata(p); printname(data);
} }
return 0; return 0;
} }
Chapter 7, Classes and Structs, presents the
fundamentals of structs and classes.
Class: Object:
•A blueprint or template for creating objects. •An instance of a class.
•Defines properties (attributes) and behaviors (methods) that •Represents a real-world entity and encapsulates both data and
objects of the class will have. behavior.
Encapsulation: Abstraction:
•The bundling of data (attributes) and methods that operate on that •Simplifying complex systems by modeling classes based on the
data into a single unit (class). essential properties and behaviors.
•Access to the internal state is controlled by public, private, and •Hides the implementation details and focuses on what an object
protected access specifiers. does rather than how it does it.
Inheritance: Polymorphism:
•A mechanism that allows a new class (derived or child class) to •The ability of different classes to be treated as objects of a common
inherit properties and behaviors from an existing class (base or base class.
parent class). •Includes function overloading and operator overloading, allowing
•Promotes code reuse and establishes an "is-a" relationship. multiple forms of a function or operator.
delete basePtr;
return 0;
}
Size of Object
#include <iostream>
class MyClass {
public:
int data;
char character;
double value;
};
int main() {
MyClass obj;
std::cout << "Size of MyClass object: " << sizeof(obj) << " bytes\n";
return 0;
}
“this” pointer – represent current instance of class
#include <iostream>
#include <iostream>
1. function overloading
2. operator overloading
3. Virtual functions
#include <iostream> // Function that uses polymorphism
#include <vector> void drawShapes(const std::vector<Shape*>& shapes) {
for (const auto& shape : shapes) {
// Base class with a virtual function shape->draw(); // Calls the appropriate draw() based on
class Shape { the actual object type
public: }
virtual void draw() const { }
std::cout << "Drawing a Shape." << std::endl;
} int main() {
}; Circle circle;
Square square;
// Derived class 1
class Circle : public Shape {
// Vector of base class pointers
public:
std::vector<Shape*> shapes;
void draw() const override {
shapes.push_back(&circle);
std::cout << "Drawing a Circle." << std::endl;
shapes.push_back(&square);
}
};
// Drawing shapes using polymorphism
// Derived class 2
drawShapes(shapes);
class Square : public Shape {
public:
return 0;
void draw() const override {
}
std::cout << "Drawing a Square." << std::endl;
}
};
Small Project – Invoice Generation for Sell
#include <iostream> // Employee Class
#include <vector> class Employee {
#include <fstream> public:
#include <sstream> std::string name;
// Product Class
class Product { Employee(const std::string& name) : name(name) {}
public: };
std::string name;
double price;
Product(const std::string& name, double price) : name(name),
price(price) {}
};
// Customer Class
class Customer {
public:
std::string name;
std::string address;
Customer(const std::string& name, const std::string& address)
: name(name), address(address) {}
};
// Invoice Class
class Invoice {
private: // DatabaseManager Class
std::vector<Product> products; class DatabaseManager {
Customer customer;
Employee employee; public:
void saveInvoice(const Invoice& invoice) {
public:
Invoice(const Customer& customer, const Employee& employee) : // For simplicity, save data to a text file
customer(customer), employee(employee) {} std::ofstream file("invoices.txt", std::ios::app);
void addProduct(const Product& product) { file << "Customer: " << invoice.customer.name << "\n";
products.push_back(product); file << "Employee: " << invoice.employee.name << "\n";
}
file << "Products:\n";
double calculateTotal() const {
double total = 0.0;
for (const auto& product : products) { for (const auto& product : invoice.products) {
total += product.price; file << "- " << product.name << " : $" << product.price <<
}
return total; "\n";
} }
void printInvoice() const {
std::cout << "Invoice\n";
std::cout << "Customer: " << customer.name << "\n"; file << "Total: $" << invoice.calculateTotal() << "\n\n";
std::cout << "Employee: " << employee.name << "\n";
std::cout << "Products:\n";
file.close();
for (const auto& product : products) {
std::cout << "- " << product.name << " : $" << product.price << "\n"; }
} };
std::cout << "Total: $" << calculateTotal() << "\n";
}
};
int main() {
// Create instances of Product, Customer, and Employee
Product laptop("Laptop", 999.99);
Product phone("Phone", 399.99);
// Create an Invoice
Invoice invoice(customer, employee);
invoice.addProduct(laptop);
invoice.addProduct(phone);
return 0;
}
Static @Compile Time
#include <iostream> int main() {
Base baseObj;
class Base { Derived derivedObj;
public:
void display() { Base* ptr = &baseObj;
std::cout << "Base display\n"; ptr->display(); // Calls Base::display() at compile time
}
}; ptr = &derivedObj;
ptr->display(); // Calls Base::display() at compile time (static
class Derived : public Base { binding)
public:
void display() { return 0;
std::cout << "Derived display\n"; }
}
};
Dynamic Binding (Late Binding) @runtime:is
associated with virtual functions.
#include <iostream> int main() {
Base baseObj;
class Base { Derived derivedObj;
public:
virtual void display() { Base* ptr = &baseObj;
std::cout << "Base display\n"; ptr->display(); // Calls Base::display() at compile time
}
}; ptr = &derivedObj;
ptr->display(); // Calls Derived::display() at runtime (dynamic
class Derived : public Base { binding)
public:
void display() override { return 0;
std::cout << "Derived display\n"; }
}
};
Static
Key Points :
•Static members are declared using the static keyword.
•Static data members must be defined outside the class, typically in a source file.
•Static member functions can only access static members (no access to non-static members
directly).
•Static members can be accessed using the class name or an object of the class (though it's
recommended to use the class name for static members).
Note: It's good practice to access static members using the class name rather than an object
#include <iostream>
int main() {
class MyClass { // Accessing static members
public: MyClass::staticVariable = 42;
// Static data member MyClass::staticFunction();
static int staticVariable;
// Creating an object
// Static member function MyClass obj;
static void staticFunction() {
std::cout << "Static function called\n"; // Accessing non-static members using the object
} obj.nonStaticVariable = 10;
obj.nonStaticFunction();
// Non-static data member
int nonStaticVariable; // Accessing static members using the object (not recommended)
obj.staticVariable = 99; // This is legal but not recommended
// Non-static member function obj.staticFunction(); // This is legal but not recommended
void nonStaticFunction() {
std::cout << "Non-static function called\n"; // Accessing static members using the class name (recommended)
} MyClass::staticVariable = 55;
}; MyClass::staticFunction();