Classes & objects
A Product class defines the data and behaviour common to industrial products. Each product in the catalogue is an object made from that class.
INDUSTRIAL EQUIPMENT / INDIA
A demo B2B catalogue for factories, workshops and construction teams. Compare industrial machines, material-handling equipment, power systems and safety supplies, then build a procurement cart.
01 / INDUSTRIAL CATALOGUE
Browse sample listings for industrial procurement. Prices and specifications are illustrative classroom data, not supplier quotations.
Try another machine name, category or search term.
SPECIFICATIONS FIRST. PROCUREMENT MADE CLEAR.
ForgeSupply is a fictional industrial marketplace concept inspired by B2B supplier catalogues. Buyers can browse machinery and industrial supplies, compare sample listings, add quantities to a cart and review an itemised estimate. Product details and prices are illustrative, not live IndiaMART listings or real quotations.
Browse equipment ↗03 / THE CORE OF THE PROJECT
ForgeSupply is a fictional industrial shopping-cart project. Its C++ companion program models products, cart items and a shopping cart using classes and objects. This guide explains the theory first, then shows exactly how each idea appears in cpp/shopping_cart.cpp.
A Product class defines the data and behaviour common to industrial products. Each product in the catalogue is an object made from that class.
Product details and cart quantities are private. Other code interacts with them through public methods, rather than changing internal state directly.
A CartItem contains a Product, and a ShoppingCart stores cart items. These objects cooperate to model the real problem.
A function template searches different kinds of objects without duplicating the search algorithm. Vectors hold collections that grow as needed.
IMPORTANT DISTINCTION The browser interface is implemented in HTML, CSS and JavaScript. The OOPS implementation described in this guide is the companion C++17 program at cpp/shopping_cart.cpp. They demonstrate the same shopping-cart idea, but are not connected to each other in this version.
04 / OOPS, FROM FIRST PRINCIPLES
Object-Oriented Programming (OOP or OOPS, Object-Oriented Programming System) is a programming approach that organises a program around objects. An object combines state (the information it holds) with behaviour (the operations it can perform). In C++, classes are the main language feature used to define these objects.
THE PROBLEM WE ARE MODELLING
A catalogue contains products. A product has an ID, a name and a price. A cart item combines a product with a chosen quantity. A shopping cart contains several cart items and calculates a subtotal or bill. OOPS lets us represent these related entities directly instead of scattering unrelated variables and functions throughout the program.
FOUR WORDS TO REMEMBER
FOUNDATION / THE LANGUAGE OF OOPS
These are the standard OOPS ideas worth understanding for a viva. The page distinguishes concepts that the current code demonstrates from concepts that are only explained for comparison.
BLUEPRINT AND INSTANCE
Definition: A class is a user-defined type that groups data members and member functions together. An object is an instance of that class. The class describes the structure; each object stores its own values.
In ForgeSupply: Product is a class. The CNC machining centre and the MIG welding machine are two different Product objects with different IDs, names and prices.
class Product {
private:
int id;
string name;
double price;
public:
int getId() const { return id; }
};
Product cnc(1, "CNC Machining Centre", 1850000);
Product welder(4, "MIG Welding Machine", 42500);
Remember: Product is the type; cnc and welder are objects. Each object has its own member values.
KEEP DATA AND RELATED METHODS TOGETHER
Definition: Encapsulation bundles data and the functions that operate on that data inside a class. It commonly uses access control to restrict direct access to internal state. This helps the class maintain valid values and reduces accidental misuse.
In ForgeSupply: Product keeps id, name and price private. Other code reads values through public getter functions. CartItem similarly keeps its quantity private and exposes controlled operations.
class Product {
private:
double price; // cannot be accessed directly from outside
public:
double getPrice() const {
return price;
}
};
For example, code cannot normally write cnc.price = -500 because price is private. The constructor also rejects a negative price. These protections work together: access control restricts who can modify data, and validation rejects invalid input.
Remember: Encapsulation is not just “putting variables in a class”. It is controlling how the object's state is accessed and changed.
SHOW WHAT AN OBJECT CAN DO, HIDE HOW
Definition: Abstraction presents a simple, relevant interface while hiding unnecessary implementation details. A user of an object should be able to use its operations without needing to know every step inside them.
In ForgeSupply: A caller can use cart.printBill(0.10) to request a bill. The caller does not have to manually loop through every cart item, calculate the subtotal, calculate the discount, estimate tax and format each line. Those details are handled inside the class.
// The caller uses a clear, high-level operation:
cart.printBill(0.10);
// Internally, printBill() checks the cart,
// calculates totals and prints the itemised bill.
Abstraction and encapsulation are related but not identical. Encapsulation concerns bundling and controlling access to internals. Abstraction concerns presenting only the essential operations to the caller.
Remember: Abstraction reduces the amount of detail a user of a class needs to understand.
CREATE A SPECIALISED CLASS FROM A BASE CLASS
Definition: Inheritance allows a new class (derived class) to reuse or extend members of an existing class (base class). It is often described as an “is-a” relationship. For example, in a different design, an IndustrialProduct might be a general base class and Machine a specialised derived class.
// Illustrative example only.
// This inheritance hierarchy is NOT in the current program.
class IndustrialProduct {
public:
string name;
};
class Machine : public IndustrialProduct {
public:
double powerRating;
};
Project status: The current C++ implementation does not use inheritance. It models products, cart items and the cart as separate classes connected by composition. That is a deliberate description of the code as it exists, not a claim that every OOPS program must use every pillar.
Remember: Inheritance is “is-a”; composition is “has-a”. A cart has cart items, it is not a type of cart item.
ONE INTERFACE, DIFFERENT BEHAVIOURS
Definition: Polymorphism means “many forms”: the same interface or operation can produce different behaviour depending on the type or object involved. In C++, common forms include compile-time polymorphism (such as function/operator overloading and templates) and runtime polymorphism (commonly virtual functions used through base-class pointers or references).
In this project: Operator overloading and templates are compile-time language features that support reusable, type-specific behaviour. However, the program does not demonstrate runtime polymorphism using virtual functions.
// Operator overloading: the + operator is defined
// for CartItem objects in a meaningful way.
CartItem operator+(int extra) const {
return CartItem(product, quantity + extra);
}
This is an example of an overloaded operator, but do not claim the project implements a virtual-function hierarchy. If asked about runtime polymorphism in the viva, define it and clearly state that it is not part of the current implementation.
Remember: Polymorphism allows a common interface to represent different behaviours; runtime polymorphism usually uses virtual functions in C++.
INITIALISE OBJECTS SAFELY
Constructor definition: A constructor is a special member function that runs when an object is created. It initializes the object and can check that the initial values are valid.
Access specifiers: private members can be accessed by the class's own member functions and permitted friends; public members form the ordinary interface available to callers; protected members are also accessible to derived classes.
Product(int productId, string productName,
double productPrice)
: id(productId),
name(std::move(productName)),
price(productPrice) {
if (price < 0)
throw invalid_argument(
"Product price cannot be negative.");
}
The colon introduces a member-initializer list, which initializes members before the constructor body executes. Here, the constructor prevents a product with a negative price from being created successfully.
Remember: Constructors initialize objects; access specifiers define who may access members.
REQUIRED IMPLEMENTATION / FIVE CONCEPTS
The following examples are based on the actual companion source file. These are the concepts to be able to point to and explain during your demonstration.
A HAS-A RELATIONSHIP
Definition: Composition is a relationship in which one object contains another object, using it as part of its structure. It is often called a “has-a” relationship. The contained object represents a component of the larger object.
In ForgeSupply: A CartItem has a Product and a quantity. A ShoppingCart has a collection of CartItem objects. This matches the domain: a line in the cart needs product details, and the cart consists of lines.
class CartItem {
private:
Product product;
int quantity;
};
class ShoppingCart {
private:
vector<CartItem> items;
};
When the constructor of CartItem receives a product, it copies that product into its product member. The cart stores cart items in its own vector. In this implementation, the contained product is stored by value, not as a pointer to a shared product object.
Viva point: “A ShoppingCart has CartItems, and each CartItem has a Product.” This is composition, not inheritance.
GIVE AN OPERATOR A CLASS-SPECIFIC MEANING
Definition: Operator overloading lets a programmer define how an existing C++ operator behaves when used with a user-defined type. It can make object operations more natural, but it does not change the operator's behaviour for built-in types such as ordinary integers.
In ForgeSupply: CartItem + 1 means “create a cart item with its quantity increased by one”. The overloaded << operator formats product and cart-item details for output streams.
CartItem operator+(int extra) const {
return CartItem(product, quantity + extra);
}
// Usage:
item = item + 1;
cout << item;
The const after the member function means the function promises not to modify the original object's members. Instead, operator+ returns a new CartItem, which is assigned back to the existing item. The stream insertion overload returns the output stream by reference so expressions such as chained output can work.
Viva point: The project overloads + for quantity updates and << for readable output.
WRITE GENERIC, REUSABLE CODE
Definition: A template is a C++ feature for writing code that can work with different types. A function template lets the compiler generate a suitable function for a type used by the program, provided that type supports the operations the function requires.
In ForgeSupply: findById searches a vector and checks each object's getId(). It can search the catalogue of Product objects without writing a separate search loop specifically for Product.
template <typename T>
int findById(const vector<T>& items, int id) {
for (int i = 0; i < static_cast<int>(items.size()); ++i)
if (items[i].getId() == id) return i;
return -1;
}
T is a placeholder for a type. The ampersand in const vector<T>& passes the vector by reference instead of copying it, and const means this function does not modify the vector. The function returns the matching index or -1 if no matching ID exists.
Viva point: Templates reduce duplicate code. The type used must provide the getId() operation that the function calls.
DYNAMIC COLLECTIONS FROM THE C++ STANDARD LIBRARY
Definition: std::vector is a sequence container that stores elements in order and can grow or shrink as elements are added or removed. Unlike a built-in fixed-size array, a vector manages its size dynamically.
In ForgeSupply: The catalogue uses vector<Product>, the shopping cart uses vector<CartItem>, and the demo order history uses vector<string>.
vector<Product> catalogue;
vector<CartItem> items;
vector<string> orderHistory;
items.emplace_back(product, quantity);
orderHistory.push_back("Demo order #1001");
emplace_back() constructs an element at the end of the vector using the supplied arguments. push_back() adds an existing value (or a value that can be constructed as an element). The program also uses indexing to access a product after the template returns its position.
Viva point: Vectors are used because the number of products or cart lines may change during execution.
HANDLE ERRORS WITHOUT SILENTLY ACCEPTING INVALID DATA
Definition: Exception handling is a mechanism for reporting and handling exceptional conditions. throw signals an error, try marks code that may produce an exception, and catch handles a matching exception.
In ForgeSupply: The code rejects negative prices, quantities below one, attempts to print a bill for an empty cart, and discount rates outside the range zero to one.
if (price < 0)
throw invalid_argument(
"Product price cannot be negative.");
try {
cart.printBill(0.10);
} catch (const exception& error) {
cerr << "Shopping cart error: "
<< error.what() << '\\n';
}
invalid_argument is used for invalid input values, while logic_error is used when billing is requested with an empty cart. The catch block in main() catches standard exceptions and prints their message. This makes invalid operations visible instead of silently continuing with an invalid result.
Viva point: throw raises the error; try surrounds risky operations; catch handles the error.
First, the catalogue vector stores Product objects. The findById template searches for a requested product. ShoppingCart::addProduct either creates a new CartItem or updates the quantity of an existing one. Composition links the cart and its items; operator+ updates quantity and operator<< prints details; vectors store the changing collections; exception handling rejects invalid inputs and billing requests. Finally, printBill calculates the subtotal, discount, estimated tax and total.
VIVA PREPARATION / CHECK YOUR UNDERSTANDING
Use these prompts to practise explaining the design in your own words, rather than memorising a paragraph and hoping the examiner is feeling generous.
Each class represents a different responsibility. Product stores product details; CartItem connects a product to a chosen quantity and line total; ShoppingCart manages multiple cart items and billing. Separating responsibilities makes the design easier to understand and maintain.
Encapsulation groups state and behaviour and controls access to internal data. Abstraction exposes a simpler interface while hiding implementation details. Private members and public getters illustrate encapsulation; calling printBill() without manually doing each calculation illustrates abstraction.
Composition is a “has-a” relationship, such as a cart having cart items. Inheritance is an “is-a” relationship, such as a hypothetical Machine class deriving from IndustrialProduct. The current project uses composition and does not implement an inheritance hierarchy.
The quantity member is private. The program changes it through class operations that validate the requested change. This keeps the object's state under the class's control.
It indicates that the member function will not modify the current object through its members. The implementation returns a new cart item with the updated quantity, and the caller can assign that result back.
It avoids writing nearly identical search functions for each supported object type. Any type passed to this function must provide the getId() method used by the search logic.
The number of cart items can change at runtime. A vector can grow as new elements are added and provides convenient operations such as size(), indexing, push_back() and emplace_back().
The product constructor throws invalid_argument for a negative price. printBill() throws logic_error if the cart is empty. The surrounding try/catch in main() catches standard exceptions and displays an error message.
No. The visible website uses JavaScript for browser interactions. The C++17 program is a separate console demonstration. Connecting them would require a backend/API, which is not included in this version.
It clearly demonstrates classes and objects, encapsulation, abstraction through public operations, and composition. It does not currently implement an inheritance hierarchy or runtime polymorphism with virtual functions. Operator overloading and templates are additional required C++ concepts demonstrated by the program.