Home | Projects | Notes > C++ Programming > Classes & Objects
Model real-world entities
Blueprint from which objects are created
A user-defined data-type
Has attributes (data; instance variables)
Has methods (functions)
Can hide data and methods that are only used internally by the class (By using access modifiers)
The goal of a class is to provide a well-defined public interface that the user of the class can easily use to solve their problem.
Examples:
Account
Employee
Image
std::vector
std::string
Created from a class
Represents a specific instance of a class
Can create many objects out of a class
Each has its own identity
Each can use the defined class methods
Examples:
Jack's account is an instance of an Account.
Sunny's account is an instance of an Account.
Each has its own balance, can make deposits, withdrawals, etc.
Player class and objects
x1// Class declaration2
3class Player4{5 // Attributes (or instance variables)6 std::string name;7 int health;8 int xp;9 10 // Methods11 void talk(std::string text_to_say);12 bool is_dead();13};xxxxxxxxxx71// Object instantiataion2
3Player jack;4Player hero;5
6Player *enemy = new Player(); // Allocated dynamically on the heap7delete enemy;Account class and objects
xxxxxxxxxx121// Class declaration2
3class Account4{5 // Attributes (or instance variables) 6 std::string name;7 double balance;8 9 // Method10 bool withdraw(double amount);11 bool deposit(double amount);12};xxxxxxxxxx101Account jack_account;2Account sunny_account;3
4Account *yena_account = new Account(); // Allocated dynamically on the heap5delete yena_account;6
7Account accounts[] {jack_account, sunny_account};8
9std::vector<Account> accounts1 {jack_account};10accounts1.push_back(sunny_account);Once declared, a class can be used just like any other C++ primitive data types.
You can access class attributes and class methods.
Some class members will not be accessible (i.e., hidden members)
Need an object to access instance variables
If you have an object, you can access the class members by using the dot operator (.).
xxxxxxxxxx41Account jack_account;2
3jack_account.balance;4jack_account.deposit(1000.00);If you have a pointer to an object, you can access the class members by using the arrow operator or member of pointer operator (->).
xxxxxxxxxx91Account *jack_account = new Account();2
3// 1. Dereference the poiner, then use the dot operator4(*jack_account).balance;5(*jack_account).deposit(1000.00);6
7// 2. Use the arrow operator (member of pointer operator)8jack_account->balance;9jack_account->deposit(1000.00);
public, private, protected)public - Accessible everywhere
private - Accessible only by other members of the same class or by friends of the class
protected - Used with inheritance
Player class
xxxxxxxxxx101class Player2{3private:4 std::string name;5 int health;6 int xp;7public:8 void talk(std::string text_to_say);9 bool is_dead();10};xxxxxxxxxx101Player jack;2jack.name = "Jack"; // Compiler error3jack.health = 1000; // Compiler error4jack.talk("Hello!"); // OK5
6Player *enemy = new Player();7enemy->xp = 100; // Compiler error8enemy->talk("Got you!");// OK9
10delete enemy;If you try to directly access a private class member from outside of the class, you will get a compiler error.
Account class
xxxxxxxxxx91class Account2{3private:4 std::string name;5 double balance;6public:7 bool withdraw(double amount);8 bool deposit(double amount);9};xxxxxxxxxx111Account jack_account;2jack_acount.balance = 1000.00; // Compiler error3jack_account.deposit(1000.00); // OK (Accessing a private member through another member of the class)4jack_account.name = "Jack's Account"; // Compiler error5
6Account *sunny_account = new Account();7
8sunny_account->balance = 10000.0; // Compiler error9sunny_account->withdraw(10000.0); // OK10
11delete sunny_account;This is very powerful, because, for example, if we have an object whose balance is 20 million dollars and we know that that must have been an error, then the only place where that error could have happened in this example is in the deposit method. There's no way that any other part of the program could have changed that value since the value is private.
This makes testing and debugging code much easier.
Very similar to how we implemented functions
Member methods have access to member attributes (Don't need to pass them as arguments as we do with regular functions!)
Can be implemented inside the class declaration
If you do this, the method becomes implicitly inline.
While this is okay for small and relatively simple methods, it is a good practice to implement larger, more complex methods outside of the class declaration.
Can be implemented outside the class declaration
To do this you need to use Class_name::method_name to tell the compiler that you are implementing a method for a specific class.
The compiler can then type check the method implementation when it sees them.
Can separate specification from implementation. This makes the class much easier to manage.
.h/.hpp file for the class declaration
cpp file for the class implementation
Implementing member methods INSIDE the class declaration
xxxxxxxxxx81class Account2{3private:4 double balance;5public:6 void set_balance(double bal) { balance = bal; }7 double get_balance() { return balance; }8};Implementing member methods OUTSIDE the class declaration
xxxxxxxxxx111class Account2{3private:4 double balance;5public:6 void set_balance(double_bal);7 double get_balance();8};9
10void Account::set_balance(double bal) { balance = bal; }11double Account::get_balance() { return balance; }Need to tell the compiler that you are implementing a method for a specific class. The compiler can then type check the method implementation when it sees them.
Separating specification from implementation
xxxxxxxxxx171/* Account.h (Specification) */2
3/* Include guard */456
7// Account class declaration8class Account9{10private:11 double balance;12public:13 void set_balance(double bal);14 double get_balance();15};16
17The include guard can be replaced by
#pragma once. But, do check first if your compiler support this directive, because some don't!
xxxxxxxxxx61/* Account.cpp (Implementation) */2
34
5void Account::set_balance(double bal) { balance = bal; }6double Account::get_balance() { return balance; }Notice that we included
Account.hand it's in double quotes. Includes with double quotes tell the compiler to include header files that are local to this project. The compiler knows where those are.Includes with angled brackets with no extensions (e.g.,
#include <iostream>) are used to include system header files and the compiler knows where these are located.
Main file
xxxxxxxxxx141/* main.cpp */2
345
6int main()7{8 Account jack_account;9 jack_account.set_balance(1000.00);10 double bal = jack_account.get_balance();11 12 std::cout << bal << std::endl; // 100013 return 0;14}Include
.hfiles and never include.cppfiles!When the program is compiled, both the
main.cppand theaccount.cppfiles are compiled and then linked to produce the executable.