프로그래밍/C++ 문법

Object-Oriented Programming in C++

studylida 2023. 2. 20. 21:00

I. Introduction to Object-Oriented Programming

Object-Oriented Programming (OOP) is a software development paradigm that uses objects and classes to model real-world problems. It is a popular programming style that is used in many programming languages, including C++. In this blog post, we will explore the fundamental building blocks of OOP, including abstraction, encapsulation, inheritance, and polymorphism, and how they are implemented in C++.

 

The fundamental building blocks of OOP are objects and classes. An object is an instance of a class, and a class is a blueprint that defines the behavior and attributes of an object. Objects are used to represent real-world objects as software objects, which helps to simplify and organize the software system.

 

OOP offers several benefits for software development, including:

  • Decreasing the complexity of software systems by breaking down problems into smaller, more manageable parts.
  • Reusability, as classes can be used and extended in multiple projects, which reduces development time and increases efficiency.
  • Extensibility, as classes can be modified and updated without affecting the entire system.
  • Maintainability, as classes can be easily updated and modified without affecting the entire system.

II. The Object Model

A. Abstraction

Abstraction is a key concept in OOP that allows objects to be represented in a simplified manner, focusing on the essential features and ignoring irrelevant details. By hiding the irrelevant details, abstraction makes it easier to understand the objects and their relationships in the software system. This allows us to create objects in software without the associated complexity in real world.

 

In C++, abstraction is represented through classes, structs, interfaces, unions, and enums. Classes and structs are used to define the behavior and attributes of an object, while interfaces and unions allow for the creation of abstract data types. Enums are used to define a set of named constants.

 

After implementing abstraction, the clint should not be able to see its internal details. So we would like to hide how the object is internally implemented. That is why we encapsulate.

B. Encapsulation

Encapsulation is another key concept in OOP, and it means hiding the implementation details of a class from the client. This is accomplished by using access modifiers, such as private and protected, which determine the level of visibility and access to the class members. This provides several benefits, including ease of use and flexible implementation changes. For example, the implementation of a class can be updated without affecting the client, as the client only interacts with the interface of the class.

C. Inheritance

Inheritance is a mechanism in OOP that allows a hierarchy of classes to be created, based on the "is-a" relationship. In other words, a child class inherits the behavior and attributes of its parent class. This allows for the reuse of classes and promotes reusability and extensibility.

 

In C++, inheritance is implemented through the use of the ":" operator, which indicates the inheritance relationship between classes. The child classes may use the member or function provided by the parent class or they can also provide a different implementation of their own.

D. Polymorphism

Polymorphism is a one of the concepts of object-oriented programming that allows representing common behavior of different objects with different implementations. Therefore, the response of the objects will be different. The response will depend on how the objects have implemented their behavior. 

 

There are several ways to implement polymorphism in C++. The following are the most common:

  1. Function overloading: In C++, it is possible to have multiple functions with the same name but with different parameters. This is known as function overloading. When a function is called, the compiler determines which version of the function to use based on the parameters provided. This allows objects to have different implementations of a function, but with the same common name.
  2. Templates: Templates are a powerful mechanism in C++ that allow the same code to be used with different types of data. By using templates, it is possible to create generic functions and classes that can work with different data types.
    1. Overloading and templates are polymorphisms that are implemented at static time, static polymorphisms.
  3. Virtual functions: Virtual functions are a feature of C++ that allow derived classes to override the behavior of functions defined in the base class. This is known as dynamic polymorphism. When a virtual function is called, the correct implementation of the function is determined at runtime, based on the type of the object. 

III. Code Examples

A. Abstraction in C++

class Student {
	int grade;
    int class;
    int gender;
	string name;
    string studentID;
};

 

B. Encapsulation in C++

Consider the example of a bank account class. A bank account can be defined as a class with behavior and implementation details, hiding the implementation details with access modifiers.

class BankAccount {
 private:
  int account_number_;
  double balance_;
  
 public:
  BankAccount(int account_number, double balance)
      : account_number_(account_number),
        balance_(balance) {}
  int account_number() const { return account_number_; }
  double balance() const { return balance_; }
  void Deposit(double amount) { balance_ += amount; }
  void Withdraw(double amount) { balance_ -= amount; }
};

C. Inheritance in C++

#include <iostream>
using namespace std;

// Base class
class Shape {
    public:
        void setWidth(int w) {
            width = w;
        }
        void setHeight(int h) {
            height = h;
        }

    protected:
        int width;
        int height;
};

// Derived class
class Rectangle: public Shape {
    public:
        int getArea() {
            return width * height;
        }
};

int main() {
    Rectangle rect;

    rect.setWidth(5);
    rect.setHeight(7);

    cout << "Total area: " << rect.getArea() << endl;
    return 0;
}

In this example, the Rectangle class is derived from the Shape class. The Rectangle class has access to the width and height variables of the Shape class because it is a protected member. The Rectangle class also has its own method getArea that calculates the area of a rectangle based on the width and height variables.

D. Polymorphism in C++

#include <iostream>
using namespace std;

// Base class
class Shape {
    public:
        virtual float area() {
            return 0;
        }
};

// Derived class 1
class Rectangle: public Shape {
    public:
        int width;
        int height;
        void setWidth(int w) {
            width = w;
        }
        void setHeight(int h) {
            height = h;
        }
        float area() {
            return width * height;
        }
};

// Derived class 2
class Triangle: public Shape {
    public:
        int base;
        int height;
        void setBase(int b) {
            base = b;
        }
        void setHeight(int h) {
            height = h;
        }
        float area() {
            return 0.5 * base * height;
        }
};

int main() {
    Rectangle rect;
    Triangle tri;

    rect.setWidth(5);
    rect.setHeight(7);

    tri.setBase(5);
    tri.setHeight(7);

    Shape *shape1 = &rect;
    Shape *shape2 = &tri;

    cout << "Total area of rect: " << shape1->area() << endl;
    cout << "Total area of tri: " << shape2->area() << endl;
    return 0;
}

In this example, polymorphism is implemented through virtual functions. The base class Shape has a virtual method area that returns 0. The derived classes Rectangle and Triangle both have their own implementation of the area method. When a pointer of type Shape is used to reference a Rectangle object or a Triangle object, the appropriate implementation of the area method is called at runtime, demonstrating polymorphism.