Greetings! Today, we're revisiting C++ classes, the core building block of Object-Oriented Programming (OOP) in C++. Through hands-on examples, we'll revisit the fundamental concepts of C++ classes, including their structure, attributes, and methods.
Let's begin with a refresher on C++ classes. Essential to OOP, C++ classes bundle relevant data and functions into compact units called objects. Consider a video game character, which is a typical example of a class instance, with specific attributes (such as health or strength) and methods (such as attack or defense).
C++1#include <iostream> 2#include <string> 3 4class GameCharacter { 5public: 6 // Constructor 7 GameCharacter(std::string name, int health, int strength) 8 : name(name), health(health), strength(strength) {} 9 10 // Method 11 void attack(GameCharacter& other_character) { 12 other_character.health -= this->strength; 13 } 14 15 // Attributes 16 std::string name; 17 int health; 18 int strength; 19};
C++ classes facilitate the grouping of associated code elements, simplifying their management. Now, to better remind ourselves how the above example works, let's go through it step-by-step.
A C++ class serves as a blueprint consisting of attributes and methods. While attributes represent data relevant to a class instance, methods are actions or functions that manipulate this data. Each class includes a constructor, which is used to define class attributes.
An essential keyword within these methods is this
, which represents the class instance. In object-oriented programming, it is needed to access the class's attributes and methods. When a new class instance is created, C++ automatically provides access to the instance through the this
pointer, allowing each object to keep track of its own state and behaviors.
C++1#include <iostream> 2#include <string> 3 4class GameCharacter { 5public: 6 // Constructor 7 GameCharacter(std::string name, int health, int strength) 8 : name(name), health(health), strength(strength) {} 9 10 // Method 11 void attack(GameCharacter& other_character) { 12 other_character.health -= this->strength; 13 } 14 15 // Attributes 16 std::string name; 17 int health; 18 int strength; 19}; 20GameCharacter character("Hero", 100, 20); // object or instance of the class 21
Attributes in C++ classes hold data associated with each class instance. For example, in our GameCharacter
class, name
, health
, and strength
are attributes. You can access a class attribute using the object of the class, followed by a dot (.
), and then the attribute name.
Attributes are initialized using a constructor, and one concise way to do this is through an initializer list. The initializer list is part of the constructor but it appears before the constructor's body. This approach is beneficial for initializing attributes efficiently, especially for constant (const) members or reference members, which must be initialized at the time of their creation.
C++1#include <iostream> 2#include <string> 3 4class GameCharacter { 5public: 6 // Constructor using an initializer list 7 GameCharacter(std::string name, int health, int strength) 8 : name(name), health(health), strength(strength) {} // initializer list (followed by an empty body) 9 10 // Attributes 11 std::string name; 12 int health; 13 int strength; 14}; 15 16int main() { 17 GameCharacter character("Hero", 100, 20); // instance of the class 18 std::cout << character.name << std::endl; // prints: Hero 19 std::cout << character.health << std::endl; // prints: 100 20 std::cout << character.strength << std::endl; // prints: 20 21 return 0; 22}
In the above example, the colon (:) after the constructor indicates the beginning of the initializer list, which initializes the class attributes with the provided arguments. Attributes differentiate one class instance from another and store the state of the instance.
A class also contains methods - actions or functions that manipulate the data in the class. For example, the attack
method in our GameCharacter
class simulates an attack by one game character on another.
C++1#include <iostream> 2#include <string> 3 4class GameCharacter { 5public: 6 // Constructor: defines class attributes 7 GameCharacter(std::string name, int health, int strength) 8 : name(name), health(health), strength(strength) {} 9 10 // Method 11 void attack(GameCharacter& other_character) { 12 other_character.health -= this->strength; // modifies 'other_character's health attribute 13 } 14 15 // Attributes 16 std::string name; 17 int health; 18 int strength; 19}; 20 21int main() { 22 GameCharacter character_1("Hero", 100, 20); // First instance of GameCharacter 23 GameCharacter character_2("Villain", 80, 15); // Second instance 24 25 std::cout << character_2.health << std::endl; // prints: 80 26 character_1.attack(character_2); // character_1 attacks character_2 27 std::cout << character_2.health << std::endl; // prints: 60, health decreased after attack 28 return 0; 29}
To deepen our understanding of C++ classes, let's explore another example where we build a basic BankAccount
class. This class will demonstrate how we can model real-world entities using object-oriented programming by defining attributes like an account holder's name and balance and methods for depositing and withdrawing money.
C++1#include <iostream> 2#include <string> 3 4class BankAccount { 5public: 6 // Constructor with a default balance of 0 7 BankAccount(std::string holder_name, double balance = 0) 8 : holder_name(holder_name), balance(balance) {} 9 10 // Method to deposit money 11 void deposit(double amount) { 12 if (amount > 0) { 13 balance += amount; 14 std::cout << amount << " deposited. New balance: " << balance << std::endl; 15 } else { 16 std::cout << "Deposit amount must be positive." << std::endl; 17 } 18 } 19 20 // Method to withdraw money 21 void withdraw(double amount) { 22 if (0 < amount && amount <= balance) { 23 balance -= amount; 24 std::cout << amount << " withdrawn. Remaining balance: " << balance << std::endl; 25 } else { 26 std::cout << "Insufficient balance for the withdrawal or amount is not positive." << std::endl; 27 } 28 } 29 30 // Attributes 31 std::string holder_name; 32 double balance; 33}; 34 35int main() { 36 BankAccount account("Alex", 1000); // An account with an initial balance of 1000 37 38 // Perform some transactions 39 account.deposit(500); // Deposit money 40 account.withdraw(200); // Withdraw money 41 std::cout << "Final balance in " << account.holder_name << "'s account: " << account.balance << std::endl; 42 return 0; 43}
This example further illustrates how classes effectively encapsulate data (attributes) and functionalities (methods), enabling us to mimic real-life scenarios. Here, the BankAccount
class allows the creation of objects representing bank accounts, emphasizing the powerful organizational benefits of using classes in C++.
Great work revisiting C++ classes, their attributes, and methods. C++ classes help organize your code, improving its readability and manageability. Now, test your understanding with exercise problems to solidify your newly refreshed knowledge. Happy coding!