MatamGuide2
MatamGuide2
תוכן העניינים
C++ ◆ Design Patterns
• Behavioral
o Iterator ............................................................................... 2
o Strategy......................................................................4
o Command ..................................................................5
• Structural
o Composite ................................................................6
o Adapter .....................................................................7
o Decorator ..................................................................8
• Creational
o Factory .....................................................................9
o Abstract Factory ...................................................... 10
o Singleton ................................................................. 11
◆ C++ basics (const, reference) ...................................................... 12
◆ Friends........................................................................................ 13
◆ Operator Overloading ................................................................. 13
◆ Function as a parameter ............................................................. 16
◆ Lambda....................................................................................... 15
◆ STL
• Using iterators in loops ....................................................... 16
• Vector ............................................................................... 17
• Map .................................................................................. 18
• Set .................................................................................... 19
• Pair & Tuple........................................................................ 19
• Queue ............................................................................... 20
• Smart Pointers ................................................................... 21
◆ Dynamic_casting ........................................................................ 21
◆ i/o stream ......................................................................... 22
◆ Exceptions ............................................................................................ 23
◆ Algorithm Library ................................................................................. 24
Python ◆ Data Structures
• String ................................................................................ 25
• List .................................................................................... 25
• Tuple ................................................................................. 26
• Set .................................................................................... 26
• Dictionary .......................................................................... 27
◆ List Comprehension .................................................................... 28
◆ Json ............................................................................................ 28
◆ File Handling ............................................................................... 29
◆ Exceptions .................................................................................. 30
◆ os and sys libraries ..................................................................... 31
Design Patterns
private:
T* ptr; // Pointer to the current element
};
// We are outside the iterator class (inside MyClass)
// Begin iterator (points to the first element)
Iterator begin() {return Iterator(data);}
Const Iterator:
template <typename T>
class MyClass {
public:
// ...
class ConstIterator {
public:
// Constructor
ConstIterator(const T* ptr) : ptr(ptr) {}
// Overloading * operator to access the value
const T& operator*() const { return *ptr; }
// Overloading ++ operator for pre-increment
ConstIterator& operator++() {
++ptr;
return *this;
}
// Overloading != operator to compare two iterators
bool operator!=(const ConstIterator& other) const {
return ptr != other.ptr;
}
private:
const T* ptr; // Pointer to the current element (const)
};
// Const begin iterator
ConstIterator begin() const { return ConstIterator(data); }
private:
// ...
};
Explanation
Example Usage
In the main() function You can create an instance of MyClass and iterate over its
elements using a range-based for loop, demonstrating both mutable and
immutable access.
▪ Strategy:
Purpose: Defines a family of algorithms, encapsulates each one, and
makes them interchangeable. The strategy pattern lets the algorithm vary
independently from clients that use it.
Use Case: When a class needs to perform a behavior (algorithm), but you
want to allow different behaviors to be defined and swapped at runtime.
Key Words (for when to use strategy):
. פעולות משתנות לפי ההתנהגות הנקבעת, בחירה בזמן ריצה,שינוי התנהגות
Example:
// Strategy Interface
class Strategy {
public:
virtual ~Strategy() = default;
virtual int execute(int a, int b) const = 0; // Pure virtual
function
};
// First strategy
class AddStrategy : public Strategy {
public:
int execute(int a, int b) const override {
return a + b;
}
};
// Second strategy
class MultiplyStrategy : public Strategy {
public:
int execute(int a, int b) const override {
return a * b;
}
};
// A Class that uses Strategy
class Calculator {
private:
std::unique_ptr<Strategy> strategy; // Pointer to Strategy
public:
// Constructor that accepts a strategy
explicit Calculator(std::unique_ptr<Strategy> strategy) :
strategy(std::move(strategy)) {}
// Set a new strategy at runtime
void setStrategy(std::unique_ptr<Strategy> newStrategy) {
strategy = std::move(newStrategy);
}
// Execute the strategy
int calculate(int a, int b) const {
return strategy->execute(a, b);
}
};
▪ Command:
Purpose: Encapsulates a request ) (פעולהas an object that contains all
the needed information to perform this request, therefore allowing us to
create store these requests objects in lists, queues….
Use Case: Used when different objects handle some requests differently,
or what requests an object should do or is allowed to do.
Key Words (for when to use command):
,(Encapsulation) הקניית פעולות, עצירת ביצוע,(𝑈𝑛𝑑𝑜) ביטול פעולה,תורים של בקשות
.ים-מניפולציות על אוביקט
Example:
// Receiver Class
class Light {
public:
void turnOn() {}
void turnoff() {}
};
// Command Interface
class Command {
public:
virtual ~Command() = default;
virtual void execute() const = 0; // Pure virtual method for
executing the command
};
// Concrete Command to turn on the light
class LightOnCommand : public Command {
private:
Light& light;
public:
explicit LightOnCommand(Light& light) : light(light) {}
void execute() const override {light.turnOn();}
};
// Concrete Command to turn off the light
class LightOffCommand : public Command {
private:
Light& light;
public:
explicit LightOffCommand(Light& light) : light(light) {}
void execute() const override {light.turnOff();}
};
// Invoker Class
class RemoteControl {
private:
std::vector<std::unique_ptr<Command>> commands;
public:
void addCommand(std::unique_ptr<Command> command) {
commands.push_back(std::move(command));
}
void pressButton() const {
for (const auto& command : commands) {command->execute();}
}
};
class Musicians{
string name; //private field
public:
virtual string playSong(string songName) const = 0;
};
▪ Adapter:
Purpose: Allowing incompatible interfaces to work together.
Use Case: When you have existing classes that don’t match the
interface you need, and you cannot or don’t want to modify them.
Key Words (for when to use adapter):
, חיבור ממשקים. שינוי ממשק, אין לשנות את המחלקה,חוסר תאימות
Example:
private:
// Pointer to an ElectricCar instance
ElectricCar* electricCar;
};
▪ Decorator:
Example:
// Base Decorator
class CoffeeDecorator : public Coffee {
public:
explicit CoffeeDecorator(Coffee* c) : coffee© {}
protected:
Coffee* coffee; // Pointer to a Coffee object
};
class Candy{};
class GummyBears:public Candy{};
class IceCream:public Candy{};
class CandyFactory{
public:
Candy* createCandy(CandyTypes type) const{
Candy* candy;
switch (type){
case (CandyTypes)gummybears:
candy = new GummyBears();
case (CandyTypes)icecream:
candy = new IceCream();
return candy;
}
}
};
int main() {
CandyFactory* candyFactory = new CandyFactory();
Candy* gummies = candyFactory->createCandy((CandyTypes)gummybears);
Candy* iceCream = candyFactory->createCandy((CandyTypes)icecream);
return 0;
}
▪ Abstract Factory:
Purpose: Providing an interface for creating related objects from the
same family or dependent objects without specifying their concrete
classes.
Use Case: When the system needs to be independent of how its products
are created, composed, or represented.
Key Words (for when to use abstract factory):
הפרדה ממימוש קונקרטי, גמישות במימוש, יצירה מופשטת,משפחות של מוצרים
Example: Given the classes: in the first section you will have to build an
Abstract factory class like shown in the second section, and then we can
run the program as shown in the third section.
// Abstract Products
class Button {
public: virtual void paint() = 0;
};
class Checkbox {
public: virtual void render() = 0;
};
// Concrete Products
class WindowsButton : public Button {
public: void paint() override{cout << "Windows Button\n";}
};
// Abstract Factory
class GUIFactory {
public:
virtual Button* createButton() = 0;
virtual Checkbox* createCheckbox() = 0;
};
// Concrete Factory
class WindowsFactory:public GUIFactory {
public:
Button* createButton() override
{ new WindowsButton();}
Checkbox* createCheckbox() override
{return new WindowsCheckbox();}
};
int main() {
GUIFactory* factory = new WindowsFactory();
factory->createButton()->paint();
factory->createCheckbox()->render();
delete factory;
}
▪ Singleton:
Purpose: Ensures that a class has only one instance and provides a
global point of access to that instance.
Use Case: When exactly one object is needed to coordinate actions
across the system.
Key Words (for when to use singleton):
. בקרת גישה, ניהול מצב משותף, גישה גלובלית,מופע יחיד
How to use:
Game::getInstance().function();
//returns a instance for the singletone class
//there can be only one object, so we delete copy constructor and assign
operator
// the constructor should be private so users can’t create new Game objects
//option 1:
class Game{
static Game* instance; // this will be initialized to nullptr
Game(){}
public:
static Game& getInstance() {
if (instance == nullptr) {
instance = new Game(); // this is called lazy initialization
}
return *instance;
}
static void destroy() { // the only way to clear the object
delete instance;
instance = nullptr;
}
Game(const Game& other) = delete;
Game& operator=(const Game& other) = delete;
};
//option 2:
class Game {
Game(){}
public:
static Game& getInstance() {
static Game instance; //created on first use
return instance; // guaranteed to be destroyed after exiting the block
}
Game(const Game& other) = delete;
Game& operator=(const Game& other) = delete;
};
C++ Basics
Const in c++: const ensures that a variable, parameter, or function return value
is read only, that means the value can’t be modified after initialization.
References in C++: A reference is like a nickname for a variable. Instead of
creating a new copy of the variable, a reference just points to the original
variable, so when you use the reference, you're working with the original data.
Passing by Value vs. Passing by Reference:
Passing by value: When an object is passed by value, a copy of the object is
made. Modifications to the object inside the function do not affect the original
object.
• Pros: Safe, because the function works with a copy of the data, avoiding
accidental changes to the original object.
• Cons: Can be inefficient if the object is large, because copying takes time
and memory.
When to use:
• When the object is small (like primitive types int, char, float).
• When you want to ensure the original object is not modified.
When to use:
• When the object is large, and you don’t want to copy it.
• When you don’t want the function to modify the original object.
Friends
Purpose: To grant external functions access to the private section of a class
Use case: for example, operator that is defined outside the class and needs to
access private fields
Operator Overloading
Purpose: allows user-defined types to behave intuitively, enabling familiar
syntax for operations, to enhances readability, and maintains consistency
across types.
What we cannot do:
Define new operators, change operators’ priority.
When overloading an operator, it should at least contain one user-defined type.
The “<<” and “>>” operators must be defined as non-members because their
first argument is an I/O stream, and not an object of the class.
Therefore, to grant them access to the private field of the class we should
define them as Friend inside the class.
class Matrix{
//...
friend ostream& operator<<(ostream& os, const Matrix& m);
}
You should also use friends at any operator that is defined outside the class
and needs to access private fields for example: For binary arithmetic operators,
you can use friend functions if you want to allow implicit type conversions or if
you want to operate on two different types.
Ways to define operators:
• Binary Operators:
o As a member function taking only one argument.
o As a nonmember function taking two arguments.
• Unary Operators:
o As a member function taking no arguments.
o As a nonmember function taking only one argument.
:: . ?: sizeof typeid
Assignment Operator:
Common Examples:
Lambda Expression
Basic syntax:
Capture List [capture]: Specifies which variables from the surrounding scope are
accessible inside the lambda. This can include by value ([x]), by reference ([&x]), or a
combination ([=, &x]).
Parameters (parameters): A list of parameters for the lambda, similar to a function’s
parameters.
Return Type -> return_type: Specifies the return type of the lambda. This is optional;
if omitted, the compiler infers the return type.
Function Body: The code to be executed when the lambda is called.
int x = 10;
auto byValue = [x]() {
cout << “Captured by value: “ << x << endl;
};
Function as a parameter
To use a function as a parameter first you should define the as follows and then
you can give it a lambda function as its inputted function:
template<class Function>
void process(int x, Function func) {
func(x);
}
STL
You can use the following method if you class implements the necessary iterator
methods (begin() and end()) and provides the appropriate iterator operations.
Example of STL classes that support this:
• Adding Elements:
• Accessing Elements:
• Size:
• Modifying Elements:
For Set and Map: we can use the .count(value) method for sets it returns the
amount of values that match the input and for map it turns the amount of keys
that match the input but we know that set values and map values are unique
therefore we can use them to check if the input is already in the set or map or
not.
Map: Usually used when we need key-value pairs with unique keys.
• Initializing:
• Adding/Modifying Elements:
• Removing Elements:
• Searching:
auto it = map.find(3);
if (it != map.end()) {
cout << “Key 3 found with the value: “ << it->second << endl;
}
//it->first points to the key, and it->second points to the value
• Accessing Elements:
• Size:
• Adding Elements:
• Removing Elements:
• Size:
Tuple: Similar to pair but can store more than two objects.
Tuple<int, string, double> myTuple(1, “one”, 3.14);
auto [num, str, pi] = myTuple; // Structured binding
Queue:
• Initializing:
queue<int> q;
• Adding Elements:
q.push(10);
• Removing Elements:
q.pop();
• Accessing Elements:
int frontElement = q.front(); // Gets the element at the front of the queue
int backElement = q.back(); // Gets the element at the back of the queue
• Size:
Smart Pointers
unique_ptr: Owns a dynamically allocated object, and no two unique pointers
can own the same object. Transfers ownership using move().
unique_ptr<int> p1 = make_unique<int>(10);
unique_ptr <int> p2 = move(p1); // p1 is now empty
Dynamic Casting
Purpose: checks at runtime whether the cast is valid. If the cast fails, it returns
nullptr (for pointer types).
It only works with classes that have at least one virtual function
Use Case: dynamic_cast is useful when you need to ensure that you are working
with the correct type in a class hierarchy, especially when dealing with base
class pointers or references that could point to different derived class objects.
Example:
i/o stream
When using a file, you should always make sure to open the file before you use it
and close the file after you are done with it. Bad file management can cause
similar problems as bad memory management.
We read and write from files using >> and << operators
For reading from a file we can use the getline() function that has two variations:
istream& getline (istream& istream, string& str);
// istream, is the file we want to read from, str is where the line will be copied.
istream& getline (istream& is, string& str, char delimiter);
//it is almost like the function up there, but you can pick to stop after reading a
specific //char instead of the default being (new line (‘\n’)).
Constructors: //constructors get the filename and open the requested file so we
can use it.
ofstream file("output.txt");
ifstream file("input.txt");
Warning! fstream objects can’t be copied, if we want to send the object to a
function, we send it as a reference or send a pointer to the object.
Exceptions (C++)
Throwing an Exception: An exception is "thrown" when an error or unexpected
event occurs. Typically, exceptions are objects of a class that inherits from
exception.
Try Block: The try block contains the code that might throw an exception. If an
exception is thrown inside the try block, control is transferred to the appropriate
catch block.
Catch Block: The catch block handles the exception. You define one or more
catch blocks to specify how different types of exceptions should be handled.
try {
if (x == 0) {
throw runtime_error("Division by zero");
}
} catch (const runtime_error& e) {
cout << "Caught an exception: " << e.what() << endl;
}
Rethrowing Exceptions: You can rethrow an exception from within a catch block
using the throw statement if you want the exception to be handled at a higher
level.
Stack Unwinding: When an exception is thrown, C++ "unwinds" the stack. This
means it calls the destructors for all local objects created in the scope of the try
block before transferring control to the catch block. This is important for
managing resources like memory or file handles.
Exception Classes: C++ provides several standard exception classes that you
can use:
Algorithm Library
sort(begin, end); // this functions starts sorting from the first to second
parameter
find(begin, end, value); //Searches for the first occurrence of a value in a range.
Python
String:
• Initializing:
str1 = "" # Empty string or you can put any string you want
• Adding Elements:
List:
• Initializing:
Tuple:
• Initializing:
Set:
• Initializing:
• Adding/Modifying Elements:
dictionary['new_key'] = 'new_value'
# Adds a new key-value pair or updates an existing key
• Removing Elements:
• Accessing Elements:
• Size:
List Comprehension
Basic Syntax:
expression: The value or computation to include in the new list.
item: The variable representing each element in the iterable.
iterable: The collection or sequence to iterate over (e.g., list, range).
condition (optional): A filter that determines if the item should be included in the new
list.
JSON files
to store an object in a JSON file you should cast the object to a dictionary and then
saving each item inside this dictionary, and then you use json.dump() to put your item
inside a file:
File Handling
Opening a file:
//using with.
with open('filename.txt', 'r') as file:
content = file.read()
# Process the content
# File is automatically closed after the block
Closing a file:
file.close()
Writing to a file:
file.write('Hello, World!\n')
file.writelines(['Line 1\n', 'Line 2\n'])
Exceptions (Python)
In Python, we handle exceptions using a try-expect block. The code that might
raise an exception goes inside the try block, and the error-handling code goes
inside the expect block.
Key Elements:
Custom Exceptions:
# this class prints a message error using the exception constructor
class MyException(Exception):
def __init__(self):
super().__init__("error message")
Useful Libraries
os Library:
Commonly used function:
os.path(file_name) # returns the path to the file name.
os.listdir(dir_name) # returns a list of the files that are in the dir
os.path.join(path, *paths) # Joins one or more path components intelligently.
os.path.split(path) # takes a file path as an argument and splits it into two
components: the directory path and the base file name. It returns a tuple containing
these two parts.
if you have a folder that contains files you can access each file using list
comprehension as follows:
sys Library:
sys.exit(0) # or 1 usually 0 indicates success while 1 indicates an error.
sys.argv # A list that contains the command-line arguments passed to a script.
Hi, everyone!
I wrote this book to help me with my MATAM exam, and I'm excited to
share it with you so that everyone can benefit from it. I hope this
makes this especially challenging year a bit easier for you.
Thank you for letting this book be a part of your study journey. Best of
luck with your exams, you’re going to do great!
Warm regards,
Sari Zrieq