C++ OOP

OOP stands for Object-Oriented Programming.

Procedural programming is about writing procedures or functions that perform operations on the data, while object-oriented programming is about creating objects that contain both data and functions.

  • OOP is faster and easier to execute
  • OOP provides a clear structure for the programs
  • OOP helps to keep the C++ code DRY “Don’t Repeat Yourself“, and makes the code easier to maintain, modify and debug
  • OOP makes it possible to create full reusable applications with less code and shorter development time

What are Classes and Objects?

Classes and objects are the two main aspects of object-oriented programming.

So, a class is a template for objects, and an object is an instance of a class.

When the individual objects are created, they inherit all the variables and functions from the class.

Attributes and Methods

Example: in real life, a car is an object. The car has attributes, such as weight and color, and methods, such as drive and brake.

Attributes and methods are basically variables and functions that belongs to the class. These are often referred to as “class members”.

class: attributes, methods——>variables, functions——>class members

Create a class

Create a class called “MyClass“:

1
2
3
4
5
6
7
8
#include <iostream>
#include <string>
using namespace std;
class MyClass { // The class
public: // Access specifier
int myNum; // Attribute (int variable)
string myString; // Attribute (string variable)
};
  • The class keyword is used to create a class called MyClass.

  • The public keyword is an access specifier, which specifies that members (attributes and methods) of the class are accessible from outside the class.

  • Inside the class, there is an integer variable myNum and a string variable myString. When variables are declared within a class, they are called attributes.

  • At last, end the class definition with a semicolon ;.

create an object

To create an object of MyClass, specify the class name, followed by the object name.

To access the class attributes (myNum and myString), use the dot syntax (.) on the object:

1
2
3
4
5
6
7
8
9
10
11
12
int main() {
MyClass myObj; // Create an object of MyClass

// Access attributes and set values
myObj.myNum = 15;
myObj.myString = "Some text";

// Print attribute values
cout << myObj.myNum << "\n";
cout << myObj.myString;
return 0;
}

create a method

There are two ways to define functions that belongs to a class:

  • Inside class definition
  • Outside class definition

Note: You access methods just like you access attributes; by creating an object of the class and using the dot syntax (.):

In the following example, we define a function inside the class, and we name it “myMethod“.

1
2
3
4
5
6
7
8
9
10
11
12
class MyClass {        // The class
public: // Access specifier
void myMethod() { // Method/function defined inside the class
cout << "Hello World!";
}
};

int main() {
MyClass myObj; // Create an object of MyClass
myObj.myMethod(); // Call the method
return 0;
}

To define a function outside the class definition, you have to declare it inside the class and then define it outside of the class. This is done by specifiying the name of the class, followed the scope resolution :: operator, followed by the name of the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyClass {        // The class
public: // Access specifier
void myMethod(); // Method/function declaration
};

// Method/function definition outside the class
void MyClass::myMethod() {
cout << "Hello World!";
}

int main() {
MyClass myObj; // Create an object of MyClass
myObj.myMethod(); // Call the method
return 0;
}

Constructors

A constructor in C++ is a special method that is automatically called when an object of a class is created.

To create a constructor, use the same name as the class, followed by parentheses ():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
using namespace std;

class MyClass { // The class
public: // Access specifier
MyClass(){ // Constructor
cout<<"Hello world"<<'\n';
}
};

int main() {
MyClass myObj; // Create an object of MyClass (this will call the constructor)
return 0;
}

Constructors can also take parameters (just like regular functions), which can be useful for setting initial values for attributes.

The following class have brand, model and year attributes, and a constructor with different parameters. Inside the constructor we set the attributes equal to the constructor parameters (brand=x, etc).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Car {        // The class
public: // Access specifier
string brand; // Attribute
string model; // Attribute
int year; // Attribute
Car(string x, string y, int z) { // Constructor with parameters
brand = x;
model = y;
year = z;
}
};

int main() {
// Create Car objects and call the constructor with different values
Car carObj1("BMW", "X5", 1999);
Car carObj2("Ford", "Mustang", 1969);

// Print values
cout << carObj1.brand << " " << carObj1.model << " " << carObj1.year << "\n";
cout << carObj2.brand << " " << carObj2.model << " " << carObj2.year << "\n";
return 0;
}

Access specifier

The public keyword is an access specifier, that defines how the members (attributes and methods) of a class can be accessed.

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 (or viewed) from outside the class
  • protected - members cannot be accessed from outside the class, however, they can be accessed in inherited classes.

Note: By default, all members of a class are private if you don’t specify an access specifier:

1
2
3
4
5
class MyClass {
//private
int x; // Private attribute
int y; // Private attribute
};

In the following example, we demonstrate the differences between public and private members:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass {
public: // Public access specifier
int x; // Public attribute
private: // Private access specifier
int y; // Private attribute
};

int main() {
MyClass myObj;
myObj.x = 25; // Allowed (public)
myObj.y = 50; // Not allowed (private)
return 0;
}

Encapsulation

The meaning of Encapsulation, is to make sure that “sensitive” data is hidden from users. To achieve this, you must declare class variables/attributes as private (cannot be accessed from outside the class). To achieve this, you must declare class variables/attributes as private (cannot be accessed from outside the class).

Access Private Members

If you want others to read or modify the value of a private member, you can provide public get and set methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
using namespace std;

class Employee
{
private:
int salary;

public:
void setSalary(int s){
salary=s;
}
public:
int getSalary(){
return salary;
}

};

int main(int argc, char const *argv[])
{
Employee myObj;
myObj.setSalary(6000);
cout<<myObj.getSalary()<<endl;
return 0;
}

Why Encapsulation?

  • It is considered good practice to declare your class attributes as private (as often as you can). Encapsulation ensures better control of your data, because you (or others) can change one part of the code without affecting other parts(when you are using multiple objects
  • Increased security of data

Inheritance

In C++, it is possible to inherit attributes and methods from one class to another. We group the “inheritance concept” into two categories:

  • derived class (child) - the class that inherits from another class
  • base class (parent) - the class being inherited from

To inherit from a class, use the : symbol.

In the example below, the Car class (child) inherits the attributes and methods from the Vehicle class (parent):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
using namespace std;

//Base Class
class Vehicle{
public:
string brand="Ford";
void honk(){
cout<<"Tuut, Tuut\n";
}

};

//Derived class
class Car: public Vehicle{
public:
string model="Mustang";
};

int main(){
Car myCar;
myCar.honk();
cout<<myCar.brand+" "+myCar.model;
}

Why And When To Use “Inheritance”?

- It is useful for code reusability: reuse attributes and methods of an existing class when you create a new class.

Multilevel Inheritance

A class can also be derived from one class, which is already derived from another class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Base class (parent)
class MyClass {
public:
void myFunction() {
cout << "Some content in parent class." ;
}
};

// Derived class (child)
class MyChild: public MyClass {
};

// Derived class (grandchild)
class MyGrandChild: public MyChild {
};

int main() {
MyGrandChild myObj;
myObj.myFunction();
return 0;
}

Multiple Inheritance

A class can also be derived from more than one base class, using a comma-separated list:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Base class
class MyClass {
public:
void myFunction() {
cout << "Some content in parent class." ;
}
};

// Another base class
class MyOtherClass {
public:
void myOtherFunction() {
cout << "Some content in another class." ;
}
};

// Derived class
class MyChildClass: public MyClass, public MyOtherClass {
};

int main() {
MyChildClass myObj;
myObj.myFunction();
myObj.myOtherFunction();
return 0;
}

Access Specifiers

The third specifier, protected, is similar to private, but it can also be accessed in the inherited class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Base class
class Employee {
protected: // Protected access specifier
int salary;
};

// Derived class
class Programmer: public Employee {
public:
int bonus;
void setSalary(int s) {
salary = s;
}
int getSalary() {
return salary;
}
};

int main() {
Programmer myObj;
myObj.setSalary(50000);
myObj.bonus = 15000;
cout << "Salary: " << myObj.getSalary() << "\n";
cout << "Bonus: " << myObj.bonus << "\n";
return 0;
}

Polymorphism

Polymorphism uses those methods that inherited from base class to perform different tasks. This allows us to perform a single action in different ways.

Just override the method from the base class in the derived class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <string>
using namespace std;
// Base class
class Animal
{
public:
void animalSound(){
cout<<"The animal makes sound"<<endl;
}
};
// Derived class
class Dog:Animal{
public:
void animalSound(){
cout<<"The dog says: wow wow"<<endl;
}
};
// Derived class
class Pig:Animal{
public:
void animalSound(){
cout<<"The pig says: wee wee"<<endl;
}
};

int main(int argc, char const *argv[])
{
Animal myAnimal;
Dog myDog;
Pig myPig;
myAnimal.animalSound();
myDog.animalSound();
myPig.animalSound();
return 0;
}

Why And When To Use “Inheritance” and “Polymorphism”?

- It is useful for code reusability: reuse attributes and methods of an existing class when you create a new class.

C++ Files

Expectations

When an error occurs, C++ will normally stop and generate an error message. The technical term for this is: C++ will throw an exception (throw an error).

  • Exception handling in C++ consist of three keywords: try, throw and catch:

    if a error is detected in the try{}, throw the exception and handle it in catch{}.

1
2
3
4
5
6
7
try {
// Block of code to try
throw exception; // Throw an exception when a problem arise
}
catch () {
// Block of code to handle errors
}
1
2
3
4
5
6
7
8
9
10
11
12
try {
int age = 15;
if (age > 18) {
cout << "Access granted - you are old enough.";
} else {
throw 505;
}
}
catch (int myNum) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Error number: " << myNum;
}