class Keywordpublic / private) & Encapsulationfstreamtry and catchstd::vector Operations (add, access, iterate)pop_back, clear, size)std::mapstd::map Operations (insert, find, iterate)You define a class using the class keyword. It acts as a container for data (attributes) and functions (methods).
This code defines a simple Car class with three data attributes.
class Car {
public: // We'll discuss this next
// Attributes (member variables)
std::string brand;
std::string model;
int year;
};
Access specifiers define how the members (attributes and methods) of a class can be accessed.
public: Members are accessible from outside the class.private: Members cannot be accessed from outside the class. This is the default if not specified.Good practice is to keep data private and expose functionality through public methods. This is called Encapsulation.
class BankAccount {
private:
// This data is safe and cannot be
// changed directly from outside.
double balance;
public:
// This function is public, so it
// can be called from outside.
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
};
Creating an object is called instantiation. You can create an object by declaring a variable of the class type, just like any other variable type (e.g., int, string).
Here, we create an instance of our Car class and access its public members using the dot operator (.).
// Create an object (instance) of the Car class
Car myCar;
// Access and set its public attributes
myCar.brand = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;
Methods are functions that belong to a class. They define the behavior of an object and can access its attributes.
This code adds a public printInfo method to the Car class, which can access the object's own data.
class Car {
public:
std::string brand;
std::string model;
int year;
// A public method
void printInfo() {
std::cout << brand << " " << model
<< " (" << year << ")";
}
};
Once you have an object, you use the dot operator (.) to call its public methods.
Car myCar;
myCar.brand = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;
// Call the method on the object
myCar.printInfo();
// Expected Output:
// Ford Mustang (1969)
A constructor is a special method that is automatically called when an object is created. It's perfect for initializing attributes.
void).This constructor for the Car class takes arguments to initialize its attributes right when the object is created.
class Car {
public:
std::string brand;
std::string model;
int year;
// The Constructor
Car(std::string b, std::string m, int y) {
brand = b;
model = m;
year = y;
}
};
Now, you can create and initialize an object in a single, clean line of code.
// Create a Car object using the constructor
Car myCar("Ford", "Mustang", 1969);
Car yourCar("Honda", "Civic", 2022);
// This is much cleaner than setting each
// member variable one by one!
// myCar.brand is already "Ford"
// myCar.model is already "Mustang"
// myCar.year is already 1969
Once data is private, we need a controlled, public way to interact with it. This is a core principle of Encapsulation.
This approach protects your data from accidental or invalid changes.
This class has private data and public methods to access and modify that data safely.
class BankAccount {
private:
std::string ownerName;
double balance;
public:
// Setter for ownerName
void setOwnerName(std::string name) {
ownerName = name;
}
// Getter for ownerName
std::string getOwnerName() {
return ownerName;
}
// Setter for balance
void setBalance(double bal) {
balance = bal;
}
// Getter for balance
double getBalance() {
return balance;
}
};
Here's how we use the public methods to interact with the object's private data.
int main() {
BankAccount myAccount;
// Use setters to modify private data
myAccount.setOwnerName("John Doe");
myAccount.setBalance(500.75);
// Use getters to retrieve private data
std::cout << "Account Owner: " << myAccount.getOwnerName() << std::endl;
std::cout << "Balance: $" << myAccount.getBalance() << std::endl;
// Direct access would cause a compile error:
// myAccount.balance = 1000000; // ERROR! 'balance' is private
return 0;
}
A major advantage of setters is adding logic to validate data before it's assigned. This protects the object's state.
class BankAccount {
private:
double balance;
public:
void deposit(double amount) {
if (amount > 0) { // Validation logic
balance = balance + amount;
} else {
std::cout << "Error: Deposit amount must be positive." << std::endl;
}
}
double getBalance() {
return balance;
}
};
// myAccount.deposit(100); // OK
// myAccount.deposit(-50); // Will print an error message
Your task is to create a Rectangle class with the following specifications:
width (double)height (double)getArea() that returns the area (width * height).getPerimeter() that returns the perimeter (2 * (width + height)).Write a main() function to create a Rectangle object and print its area and perimeter to the console.
Create a Book class that demonstrates good encapsulation:
title (std::string)author (std::string)pages (int)getTitle(), getAuthor(), and getPages().setPages(int p) that only changes the page count if the new value p is greater than zero.In main(), create a Book, print its details, try to set an invalid page count, then set a valid one, and print the details again.
C++ provides the `fstream` library for working with files. This library includes three classes: `ifstream` for reading from files, `ofstream` for writing to files, and `fstream` for both reading and writing.
This code shows how to write to a text file.
#include <iostream>
#include <fstream>
int main() {
std::ofstream MyFile("filename.txt");
MyFile << "Files can be tricky, but it is fun enough!";
MyFile.close();
return 0;
}
You can read from a file line by line using a `while` loop with `getline()`.
This code reads a text file and prints its contents to the console.
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::string myText;
std::ifstream MyReadFile("filename.txt");
while (getline(MyReadFile, myText)) {
std::cout << myText;
}
MyReadFile.close();
return 0;
}
Exception handling is a mechanism to handle runtime errors. C++ provides three keywords for this: `try`, `catch`, and `throw`.
This code shows how to use `try` and `catch` to handle a division by zero error.
try {
int age = 15;
if (age >= 18) {
std::cout << "Access granted - you are old enough.";
} else {
throw (age);
}
}
catch (int myNum) {
std::cout << "Access denied - You must be at least 18 years old.\n";
std::cout << "Age is: " << myNum;
}
Namespaces provide a solution for preventing name conflicts in large projects. The `using namespace` directive can be used to avoid having to prefix standard library names with `std::`.
This code shows how to use the `std` namespace for different libraries.
#include
#include
#include
// Import only specific items you need
using std::cout;
using std::endl;
using std::vector;
using std::string;
int main() {
vector numbers = {1, 2, 3, 4, 5};
string message = "Hello World";
cout << message << endl;
for (int num : numbers) {
cout << num << " ";
}
cout << endl;
return 0;
}
}
The STL is a set of C++ template classes to provide common programming data structures and functions such as lists, stacks, arrays, etc. It is a library of container classes, algorithms, and iterators.
Some of the most common STL containers include:
A `std::vector` is a sequence container that encapsulates dynamic size arrays. It is part of the C++ Standard Template Library (STL).
To use `std::vector`, you need to include the `
#include <vector>
std::vector<int> myVector;
You can add elements to the end of a vector using the `push_back()` member function.
This code adds three integers to a vector.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector;
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
return 0;
}
You can access elements of a vector using the `[]` operator or the `.at()` member function. `.at()` provides bounds checking and will throw an exception if you try to access an out-of-bounds element.
This code accesses the second element of the vector.
std::vector<int> myVector = {10, 20, 30};
int secondNumber = myVector[1];
int thirdNumber = myVector.at(2);
You can get the number of elements in a vector using the `.size()` member function.
This code prints the size of the vector.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {10, 20, 30};
std::cout << "The size of the vector is: " << myVector.size();
return 0;
}
You can iterate through a vector using a traditional `for` loop, a range-based `for` loop, or iterators.
This is the most common and convenient way to iterate through a vector.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {10, 20, 30};
for (int element : myVector) {
std::cout << element << " ";
}
return 0;
}
You can create vectors of any type, including your own custom classes.
This program creates a vector of strings, adds items, and then prints them.
#include <iostream>
#include <vector>
#include <string>
int main() {
// Vector of strings
std::vector<std::string> fruits;
fruits.push_back("Apple");
fruits.push_back("Banana");
fruits.push_back("Orange");
std::cout << "We have " << fruits.size() << " fruits:" << std::endl;
for (const std::string& fruit : fruits) {
std::cout << "- " << fruit << std::endl;
}
return 0;
}
This example demonstrates adding, removing, and clearing elements.
std::vector<int> numbers = { 1, 2, 3, 4, 5 };
// numbers contains {1, 2, 3, 4, 5}, size is 5
numbers.pop_back(); // Removes the last element (5)
// numbers contains {1, 2, 3, 4}, size is 4
// Access and modify an element
numbers.at(0) = 99;
// numbers contains {99, 2, 3, 4}
if (!numbers.empty()) {
std::cout << "Vector is not empty." << std::endl;
}
numbers.clear(); // Removes all elements
// numbers is empty, size is 0
if (numbers.empty()) {
std::cout << "Vector is now empty." << std::endl;
}
You can store objects of your own classes in a vector.
class Student {
public:
std::string name;
int id;
Student(std::string n, int i) : name(n), id(i) {}
};
int main() {
std::vector<Student> classList;
classList.push_back(Student("Alice", 101));
classList.push_back(Student("Bob", 102));
for (const Student& s : classList) {
std::cout << "ID: " << s.id << ", Name: " << s.name << std::endl;
}
return 0;
}
A `std::map` is an associative container that stores elements in a mapped fashion. Each element has a key value and a mapped value. No two mapped values can have the same key values.
To use `std::map`, you need to include the `
#include <map>
#include <string>
std::map<std::string, int> myMap;
You can insert elements into a map using the `[]` operator or the `insert()` member function.
This code inserts three key-value pairs into a map.
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
ages.insert(std::make_pair("Charlie", 35));
return 0;
}
You can access the value associated with a key using the `[]` operator or the `.at()` member function. `.at()` provides bounds checking.
This code accesses the age of Bob.
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
int bobsAge = ages["Bob"];
You can check if a key exists in a map using the `.count()` or `.find()` member functions.
This code checks if the key "David" exists in the map.
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 30;
if (ages.count("David")) {
std::cout << "David is in the map.";
} else {
std::cout << "David is not in the map.";
}
return 0;
}
You can iterate through a map using a range-based `for` loop or iterators.
This is a convenient way to iterate through a map.
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
for (const auto& pair : ages) {
std::cout << pair.first << " is " << pair.second << " years old.\n";
}
return 0;
}
Use a map when you need to store and retrieve data based on a unique key. It's a great choice for implementing look-up tables, dictionaries, and frequency counters.