Computer Science/C++

[C++] 객체 지향 프로그래밍, 클래스, 접근 지시자 - 씹어먹는 C++ 4강

토마토. 2021. 7. 19. 14:00

객체 지향 프로그래밍의 도래

 

프로그래밍 언어의 발전

1세대 프로그래밍 언어는

진공관 선을 조정해서 명령을 내리는 수준이었다.

ex) ENIAC

 

컴퓨터 내장 메모리가 만들어지면서

2세대 프로그래밍 언어가 등장한다. 

대표적인 사례가 assembly language이다.

0과 1로 이루어진 기계어에

문자열을 대응시킨 것에 가깝다. 

그래서 저수준 low-level 언어라고 한다.

 

그러나 2세대 언어는

구조가 체계적이지 않아 

논리구조가 뒤엉켜 오류를 찾기 힘든 '스파게티 코드'가 만들어지기 쉬웠다.

 

그래서 등장한 것이

3세대 프로그래밍 언어 - procedural programming language이다.

pascal, C가 대표적이다.

'procedure'를 지향한다는 것은

다르게 표현하면, 함수를 지향하는 것과 같다.

중요한 부분을 하나의 절차로 만들어 쪼개어 처리한다는 것이다.

 

절차 지향 언어는 객체지향언어로 발전하였다.

C#, python, java, C++ 등이 객체지향언어에 해당한다.

 

 

 

객체란? 

 

지난 장의 코드를 떠올려보자. 

#include <iostream>

typedef struct Animal {
  char name[30];
  int age;
  int health;
  int food;
  int clean;
} Animal;

void create_animal(Animal *animal){
  std::cout<<"name : ";
  std::cin >> animal->name;

  std::cout<<"age : ";
  std::cin >> animal->age;

  animal->health = 100;
  animal->food = 100;
  animal->clean = 100;
}

void play(Animal *animal){
  animal->health += 10;
  animal->food -= 20;
  animal->clean -= 30;
}

void one_day_pass(Animal *animal){
  animal->health -= 10;
  animal->food -= 30;
  animal->clean -= 20;
}

void show_stat(Animal *animal){
  std::cout << "name : " << animal->name << std::endl;
  std::cout << "health : " << animal->health << std::endl;
  std::cout << "food : " << animal->food << std::endl;
  std::cout << "clean : " << animal->clean << std::endl;
}

int main(){
  int animal_num = 0;
  Animal *list[10];
  while (1) {
    std::cout << "1. 동물 추가하기 " << std::endl;
    std::cout << "2. 놀아주기 " << std::endl;
    std::cout << "3. 상태 보기" << std::endl;
    std::cout << "4. 끝" << std::endl;

    int input;
    std::cin >> input;
    if (input==4){
      break;
    }
    switch(input){
      int play_with;

      case 1:
        list[animal_num] = new Animal;
        create_animal(list[animal_num]);

        animal_num++;
        break;
      case 2:
        std::cout << "who?";
        std::cin >> play_with;
        if (play_with < animal_num){
          play(list[play_with]);
        }
        break;

      case 3:
        std::cout <<"who?";
        std::cin >> play_with;
        if (play_with < animal_num){
          show_stat(list[play_with]);
        }
        break;


    }

    for (int i = 0; i != animal_num; i++){
      one_day_pass(list[i]);
    }
  }
  for (int i = 0; i != animal_num; i++){
    delete list[i];
  }
  return 0;
}

[C++] C++ new, delete - 씹어먹는 C++ 3강 (tistory.com)

여기서는

animal 구조체를 이용하여 animal의 정보를 형성한 뒤에

따로 create, play, show_stat 함수를 만들어 animal의 정보를 넘겼다.

 

만약에

다양한 animal 종류를 만들거나

animal 정보에 복잡한 조작을 하게 되면

코드가 더 복잡해지게 된다. 

 

animal 정보(변수)와 조작(함수)를 한 번에 처리할 수 있으면 좋지 않을까?

라는 생각이 만들어낸 것이 '객체' 개념이다.

 

객체란 무엇인가?

 

객체는 변수와 함수로 이루어진 소프트웨어 덩어리이다.

이때 함수는 변수가 하는 행동들을 수행하게 된다.

 

객체는 추상화 과정을 통해서

컴퓨터에서 처리할 수 있도록 만든다. 

객체는 자기 만의 정보를 나타내는 변수(instance variable)

이러한 변수를 가지고 어떠한 작업을 하는 함수(instance method)로 구성된다.

 

객체의 변수는 instance method 함수를 통해서만 간접적으로 조절할 수 있다.

이렇게 인스턴스 메소드를 통해

인스턴스 변수값을 간접적으로 조절하는 것을

캡슐화 encapsulation이라고 한다.

 

캡슐화를 통해서

객체가 내부적으로 어떻게 작동하는지 몰라도

객체를 사용할 수 있게 된다.

 

클래스란? 

C++에서는 클래스를 통해 객체를 만든다.

각 객체는 instance라고 한다.

그래서 객체의 변수를 instance variable

객체의 함수를 instance method라고 하는 것이다. 

 

클래스 예시

#include <iostream>

class Animal{
  private:
    int food;
    int weight;
  public:
    void set_animal(int _food, int _weight){
      food = _food;
      weight = _weight;
    }

    void increase_food(int inc){
      food += inc;
      weight += (inc/3);
    }

    void view_stat(){
      std::cout <<"food : " << food << std::endl;
      std::cout << "weight : "<< weight <<std::endl;
    }
};

실행 예시

int main(){
  Animal animal;
  animal.set_animal(100,50);
  animal.increase_food(30);

  animal.view_stat();
  return 0;
}

2줄 Animal animal;은

Animal 클래스의 animal instance를 생성했다는 것이다.

이전과 같이 배열을 이용하여 표현하지 않아도 된다.

 

클래스 상에서

food, weight와 같은 변수는 member variable,

set_animal, increase_food와 같은 함수는 member function이라고 한다.

 

접근 지시자 - public, private

 

생각해볼 문제

Date 클래스를 디자인하려고 한다. 

SetDate

AddDay

AddMonth

AddYear

ShowDate 함수를 구현하라

 

#include <iostream>
class Date {
  int year_;
  int month_;  // 1 부터 12 까지.
  int day_;    // 1 부터 31 까지.

 public:
  void SetDate(int year, int month, int day){
    year_ = year;
    month_ = month;
    day_ = day;
  }

  void AddDay(int inc){
    day_ += inc;
    if (month_ == 2){
      if (day_ > 28){
        day_ %= 28;
        AddMonth(day_/28);
      }
    }
    else if (month_ == 1||month_ == 3||month_ == 5||month_ == 7||month_ == 8||month_ == 10||month_ == 12){
      if (day_ > 31){
        AddMonth(day_/31);
        day_ %= 31;
        


      }
    }
    else {
      if (day_ > 30){
        
        AddMonth(day_/30);
        day_ %= 30;
      }
    }
  }

  void AddMonth(int inc){
    month_ += inc;
    if (month_ > 12){
      
      year_ += (month_) / 12;
      month_ %= 12;
    }
  }
  void AddYear(int inc){
    year_ += inc;
  }

  void ShowDate(){
    std::cout<< year_ << "년" << month_ << "월" << day_ << "일" << std::endl;
  }
};

int main(){
  Date mon;
  mon.SetDate(2000, 10, 10);
  mon.AddDay(30);
  mon.ShowDate();

  mon.AddMonth(1);
  mon.AddYear(10);
  mon.ShowDate();
  return 0;
}