wn42
코딩이랑 이것저것
wn42
전체 방문자
오늘
어제
  • 분류 전체보기 (113)
    • 프로그래머스 (23)
      • LV1 (11)
      • LV2 (1)
      • LV3 (3)
      • 연습 (8)
    • 딥러닝 공부 (0)
      • 머신러닝&딥러닝 이론 (0)
    • 임베디드 (17)
      • Adventure Design (1)
      • 센서기반모바일로봇 (5)
      • ROS (9)
      • Google Coral (2)
    • C++ (38)
      • C++ 기초 (34)
      • 자료구조 및 알고리즘 (4)
    • Python (14)
      • 기본 파이썬 문법 (6)
      • Python 기초 (8)
    • 빅데이터 (9)
      • 빅데이터 첫걸음 시작하기(국비지원) (5)
      • 빅데이터 공부 (4)
    • 알고리즘 공부 (2)
      • 기본 알고리즘 (2)
    • 전자공학 (10)
      • 반도체 공정 (3)
      • 무선데이터통신 (7)
      • 반도체공학 (0)
    • C# (0)
      • C# 기본 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ROS
  • 반복문
  • 변수
  • 조건문
  • K디지털크레딧
  • 스택/큐
  • numpy
  • 노드
  • 빅데이터 첫걸음 시작하기
  • 패스트캠퍼스
  • Queue
  • 파이썬
  • google coral
  • 스택
  • 큐
  • Python
  • 클래스
  • 인스턴스
  • 상속
  • 소멸자
  • 빅데이터
  • 딥러닝
  • 데이터분석
  • stl
  • 프로그래머스
  • 내일배움카드
  • 바이트디그리
  • c++
  • 데이터분석 인강
  • 정렬

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
wn42

코딩이랑 이것저것

[C++] 객체 지향 프로그래밍
C++/C++ 기초

[C++] 객체 지향 프로그래밍

2023. 1. 2. 16:58

 객체 지향 프로그래밍 

객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다.

  • 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. ▶ 객체: 하나의 역할을 수행하는 '메소드와 변수(데이터)'의 묶음
  • 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.

 

절차적 프로그래밍

  • Procedure-Oriented Programming (POP)
  • 프로시저 호출의 개념을 바탕으로 하고 있는 프로그래밍 패러다임의 일종
  • 프로시저: 루틴, 하위프로그램, 서브루틴, 메서드, 함수라고도 하며, 수행되어야 할 연속적인 계산 과정을 포함한다.
  • 프로그램의 아무 위치에서나 프로시저를 호출할 수 있고, 다른 프로시저에서도 호출이 가능하다. 심지어는 자기 자신에서도 호출이 가능하다.
  • 절차적 프로그래밍을 따르는 대표적인 언어로는 C, Fotran 등이 있다.

 

장점

  • 반복적인 동작을 함수로 구현하기 때문에 코드의 재활용성이 높고, 코드의 길이가 줄어든다.
  • 함수의 호출을 통해 여러 부분을 생략하여 프로그램의 흐름을 쉽게 파악할 수 있어 코드의 가독성이 높아진다.

 

단점

  • 코드 간 유기성이 높아 유지보수가 어렵다. ▶ 조금만 복잡해져도 "스파게티 코드"가 될 가능성이 높음
  • 실행 순서가 정해져 있어 코드 순서가 바뀌면 동일한 결과를 보장하기 어렵다.
  • 디버깅이 어렵다.

 

 

객체 지향 프로그래밍

  • Object-Oriented Programming (OOP)
  • 객체라는 작은 단위에서 프로그램이라는 큰 단위로 나아가는 Bottom-up 방식 (상향식)
  • 객체를 하나의 레고처럼 각각을 끼워 맞추며 프로그램을 만든다고 생각하면 된다.
  • 대표적인 언어로는 C++, Python, Java 등이 있다.

 

장점

  • 객체간 독립성이 높다. (dependecy가 낮다.) ▶ 각 객체를 독립적으로 운용할 수 있어 유지보수가 용이하다.
  • 각 기능을 모듈화함으로써 재활용성이 높아진다.
  • 불필요한 연산을 줄이고 하드웨어의 연산 처리량을 획기적으로 줄일 수 있다.
  • 대형 프로젝트에 적합한 프로그래밍이다. 업무를 분담하기에 알맞다.
  • 디버깅이 쉽다.

 

단점

  • 객체가 많아지고, 코드가 길어질수록 용량이 매우 커지고, 프로그램 속도도 느려진다.
  • 절차적 프로그래밍보다 상대적으로 설계 시간이 오래 걸린다.

 

 

절차적 프로그래밍 vs 객체 지향 프로그래밍

  • 절차적 프로그래밍과 객체 지향 프로그래밍은 상반된 개념이 아니다.
  • 절차적이지 않은 프로그래밍은 없다.
  • 절차적 프로그래밍은 "절차 = 프로시저"라는 기능 단위로 진행하는 방식이며, 객체 지향 프로그래밍은 "객체"라는 단위로 진행되는 방식이다. ▶ POP - 절차, 순서에 집중. OOP - 객체들의 속성, 종류 등에 집중
  절차적 프로그래밍(POP) 객체 지향 프로그래밍(OOP)
접근 방식 Top-Down Bottom-Up
구성 요소 기능(Function/Procedure) 객체(Object)
접근 제한자 X (모두 Public) Public, Protected, Private
다형성 X O
상속 X O (Public, Protected, Private)
보안 낮음 높음
Friend 기능 X C++에 있음
가상 클래스 or 함수 X 상속 하에 있음
코드 재활용 X O
장점 코드 작성이 쉬운 편 코드를 효율적으로 작성
단점 규모가 큰 프로젝트에서는 코드가 복잡해지고 중복될 가능성이 높음 객체가 많아질수록 오버헤드가 늘어 상대적으로 자원과 시간을 많이 소비
대표 언어 C, VB, FORTRAN, Pascal C++, JAVA, VB.NET, C#.NET

 

 

객체 지향 프로그래밍의 특징

  • OOP 특징은 대표적으로 추상화, 캡슐화, 상속, 다형성 총 4가지를 설명한다.

 

1. 추상화 (abstraction)

  • 객체들의 공통적인 특징(기능, 속성)을 추려내는 것
  • 불필요한 부분을 생략하고 객체의 속성 중 중요한 것에만 중점을 두어 개략화한다.
  • 추상화를 이용하면 코드의 재사용성, 가독성이 높아지고, 유지보수에 있어 많은 시간을 절약할 수 있다.
  • 객체 지향적 관점에서는 클래스를 정의하는 것을 추상화라고 할 수 있다.

 

예시

  • 위는 대표적인 IT 업계들인 네카라쿠배당토이다.
  • 네이버, 카카오, 라인 등을 각각 객체라고 할 수 있으며, 이들을 대형 IT 기업이라는 큰 틀로 묶을 수 있겠다.
  • 그리고 대형 IT 기업이라는 큰 틀(클래스)에서 프로그래밍, B2C 서비스, 이직이 쉬움 등의 공통적인 특징을 정의할 수 있다. 이렇게 공통적인 특징을 추려내는 과정이 추상화이다.
  • 추상화를 완료하면, 큰 틀(클래스)을 기준으로 각 객체가 갖는 개별적인 특징만 정의하면 된다. (ex. 네이버 - 웹엔진, 당근마켓 - 소셜 커머스, 토스 - 금융 등)

 

2. 캡슐화 (Encapsulation)

  • 객체의 데이터와 기능을 하나로 묶고 외부에 노출되지 않도록 은닉하는 것
  • 모듈 내 높은 응집도, 모듈 간 낮은 결합력
  • 변수, 메소드, 클래스에 대해 접근 제어자를 사용하여 캡슐화할 수 있다.
  • 외부에서 객체의 속성 및 메소드에 접근할 수 없게 하여, 외부에서의 잘못된 접근과 조작으로 인한 객체 손상을 방지할 수 있다.

 

예시

  • 자동차는 가속 페달을 밟으면 차의 속도가 빨라지고, 브레이크 페달을 밟으면 속도가 느려진다.
  • 우리는 가속 페달을 밟으면 왜 빨라지는지, 브레이크 페달을 밟으면 왜 느려지는지 그 이유를 알지 못한다. 그렇지만 그 사실을 알지 못하더라도 우리는 자동차를 운전할 수 있다.
  • 그런데 갑자기 굳이 내부적인 구조가 궁금해서 자동차 차체를 뜯어 보았고, 이후 다시 조립하는 과정에서 가속 페달과 브레이크 페달의 연결선을 반대로 끼워 버렸다.
  • 이제부터는 브레이크 페달을 밟으면 속도가 빨라지고, 가속 페달을 밟으면 속도가 느려진다.
  • 이를 원상 복구 하기가 매우 어렵고 귀찮아서 그대로 운전을 했고, 결국 멈춰야 할 때 차를 가속시키는 실수를 하여 교통사고를 발생시켰다.
  • 자동차 회사 측은 이러한 황당한 짓을 하는 사람을 보고는 절대로 차체를 뜯어볼 수 없도록 막아버렸고, 누구도 가속 페달과 브레이크 페달의 기능을 뒤바꾸어 버리는 실수를 하지 않게 되었다.
  • 이러한 회사 측의 행동은 객체의 손상을 막기 위한 캡슐화 과정이라고 볼 수 있겠다.

 

3. 상속 (inheritance)

  • 상위 개체의 특성(속성, 기능)을 하위 개체가 그대로 물려받는 것
  • 이미 작성된 클래스를 그대로 재사용하여 새로운 클래스를 만드는 것이다.
  • 모든 기능을 그대로 사용하지 않고, 일부를 수정하여 다시 정의할 수 있다. ▶ 오버라이딩(overriding)
  • 상속은 OOP의 특징인 캡슐화를 유지하면서도 클래스의 재사용을 용이하게 해준다.

 

예시

  • Animal은 동물이라는 최상위 개념이며, 살아 움직이고 뇌가 있고, 다리가 있다는 특성을 갖는다.
  • Animal이라는 상위 개념에서 Human, Dog라는 하위 개념을 정의할 수 있다. Human과 Dog는 상위 개념인 Amimal의 특성을 그대로 가지면서도 각 객체의 고유한 특성 또한 갖고 있다.
  • 다시 Dog의 하위 개념으로 말티즈와 웰시코기를 정의할 수 있다. 말티즈와 웰시코기 또한 상위 개념인 Dog의 특성을 가지면서도 각 객체의 고유한 특성을 갖고 있다.
  • 예시처럼 상위 개념의 특성을 하위 개념이 물려 받는 것을 상속이라고 한다.

 

상속의 장점

  • 객체를 만들어 놓고 언제든지 다시 사용할 수 있어 재사용성이 높아진다.
  • 상위 클래스를 그대로 사용하기 때문에 하위 클래스를 만드는 데 걸리는 시간이 단축된다.
  • 하위 클래스를 일일이 수정할 필요 없이 상위 클래스를 수정하면 되기 때문에 유지보수가 용이하다.

 

상속의 단점

  • 상위 클래스의 내부 구현이 달라지면 하위 클래스에 영향을 끼친다. 따라서 모든 하위 클래스의 기능 또한 수정해야 할 가능성이 있다. ▶ 하위 클래스가 상위 클래스에 대해 강한 결합력을 갖고, 객체 내에서는 약한 응집력을 가지는 수동적인 객체가 됨.
  • 하위 클래스의 기능 확장을 위해, 상위 클래스의 정보를 파헤쳐 보안 허점이 발생할 수 있다.
  • 클래스의 기능을 재사용하기 위한 목적으로 상속하는 경우, 엉뚱한 is-a 관계로 인해 의도치 않은 동작이 이루어질 수 있다.

 

상속 대신 조합(Composition)

  • 조합(Composition): 기존 클래스가 새로운 클래스를 구성하기 위한 요소로 쓰임. ▶ 레고 조립을 생각
  • is-a 관계(상속): 사람은 동물이다. / 사과는 과일이다. / 자동차는 이동수단이다. 등..
  • has-a 관계(조합): 사람은 눈이 있다. / 컴퓨터는 연산장치를 가진다. / 자동차는 엔진을 가진다. 등..
  • 조합을 사용하는 경우, 하위클래스는 상위 클래스를 메소드로서 호출하기 때문에 캡슐화를 유지하면서도, 의존적이지 않게 되므로 상위 클래스의 변화가 끼치는 영향이 줄어든다.

 

상속은 언제 사용해야 하는가?

  • 반드시 조합을 사용하는 것이 능사는 아니다. 특정 상황에서는 상속이 더욱 강력하고 편리하게 사용된다.
  • 1. is-a 관계가 명확할 때 사용한다.
  • 2. 코드의 재사용 보다는 기능 확장의 관점에서 상속을 사용한다.
  • 3. 상위 클래스의 메소드를 절대로 바꾸지 않을 것이라고 생각될 때 사용한다.

 

4. 다형성 (Polymorphism)

  • 상속받은 메소드나 클래스가 서로 다른 클래스에서 다양한 방식으로 동작하는 것
  • 다형성을 통해 확장성과 유연성이 높아진다.
  • 대표적으로 오버로딩(overloading), 오버라이딩(overriding)이 있다.

 

예시

  • 다형성을 나타내는 하나의 예시이다.
  • Dog 클래스에는 Bark()라는 메소드가 있다. (짖다)
  • 말티즈와 웰시코기는 Dog의 하위 클래스이기 때문에 Bark() 메소드를 사용할 수 있다.
  • 이 메소드를 각각의 객체에서 실행했을 때, 개마다 소리가 다르기 때문에 말티즈는 Yip!! 하면서 짖고, 웰시코기는 Woof!! 하면서 짖는다.

 

오버로딩(overloading)

  • 함수명이 같은 함수(메소드)를 중복 정의하는 것
  • 매개변수 자료형과 개수에 따라 동일한 이름을 갖는 여러 개의 함수를 만들 수 있다.
  • 다음은 같은 이름(sum)을 갖는 함수를 중복한 오버로딩 예시이다.
#include <iostream>
using namespace std;

class Math {
public:
    int sum(int a, int b) {
        cout << "정수의 합: ";
        return a + b;
    }
    
    float sum(float a, float b) {
        cout << "실수의 합: ";
        return a + b;
    }
};

void main() {
    Math math;
    cout << math.sum(3, 5) << endl;
    cout << math.sum(3.6f, 3.7f) << endl;
}
정수의 합: 8
실수의 합: 7.3

 

오버라이딩(overriding)

  • 상속받은 부모 클래스의 메소드를 그대로 사용하지 않고 자식클래스에서 기능을 재정의하여 사용하는 것
  • 오버라이딩은 다음을 준수하여야 한다.
    • 상위 클래스에 오버라이드하려는 메소드가 반드시 있어야 함
    • 메소드 명이 같아야 함
    • 메소드의 매개변수의 개수 및 자료형이 동일해야 함
    • 메소드의 반환형이 같아야 함
  • 다음은 하위 클래스에서 상위 클래스의 메소드(Bark)를 재정의한 오버라이딩 예시이다.
#include <iostream>
using namespace std;

class Dog {
public:
    void Bark(int a) {
        for (int i = 0; i < a; i++) {
            cout << "Bow-wow!!" << " ";
        }
        cout << endl;
    }
};

class Maltese : public Dog {
public:
    void Bark(int a) {
        for (int i = 0; i < a; i++) {
            cout << "Yip!!" << " ";
        }
        cout << endl;
    }
};

void main() {
    Dog dog;
    Maltese maltese;
    dog.Bark(3);
    maltese.Bark(3);
}
Bow-wow!! Bow-wow!! Bow-wow!!
Yip!! Yip!! Yip!!

더보기

SOLID

객체 지향 5원칙

 

 

 

 

    'C++/C++ 기초' 카테고리의 다른 글
    • [C++] 생성자 (Constructor)
    • [C++] 객체, 인스턴스, 클래스
    • [C++] 동적 메모리 할당
    • [C++] 레퍼런스(참조자)
    wn42
    wn42
    코딩이랑 이것저것 하는 블로그

    티스토리툴바