객체, 인스턴스, 클래스
OOP의 요소인 객체, 인스턴스, 클래스에 대해서 알아보자
- 클래스 - 붕어빵 틀
- 객체 - 붕어빵 (클래스라는 붕어빵 틀에서 나온 모든 붕어빵)
- 인스턴스 - 굽기, 팥의 양 등에 따라 맛이 다른 붕어빵들 ▶ 객체(붕어빵)를 인스턴스화(굽기, 팥의 양 등을 조절)한 것
- 일단은 이렇게만 알고 들어가자
객체 (object)
- OOP에서 클래스(class)가 실제로 구현된 인스턴스(instance) ▶ 클래스를 인스턴스화한 것
- 위 그림처럼 하나의 객체는 데이터와 함수를 모두 포함할 수 있다. ▶ 데이터와 함수를 각각, 인스턴스 변수(instance variable), 인스턴스 메소드(instance method)라고 한다.
- 그림을 보면 변수는 메소드라는 벽에 둘러싸여 보호받고 있다. 이는 인스턴스 변수에 직접 접근하는 것은 불가능하고, 인스턴스 메소드를 통해서만 접근 및 수정이 가능하다는 것을 의미한다. 즉, 캡슐화(encapsulation)가 이뤄진다.
인스턴스 (instance)
- OOP에서 클래스(class)에 소속된 개별적인 객체(object)
- 객체를 실제로 만든것, 즉 메모리 공간에 구현된 실체이다. ▶ 객체는 선언, 인스턴스는 실체화를 의미
- 하나의 클래스에는 여러 개의 인스턴스를 생성할 수 있다.
- 인스턴스는 독립된 메모리 공간에 자신만의 멤버 변수를 갖지만, 멤버 함수는 모든 인스턴스가 공유한다.
- 많은 곳에서 객체와 인스턴스를 혼용해서 사용하지만 근본적으로 같은 것은 아니다.
- 객체 - 소프트웨어 세계에 구현할 대상, 인스턴스 - 소프트웨어 세계에 구현된 실체
- 객체 - 클래스의 타입으로 선언된 것, 인스턴스 - 선언된 객체가 메모리에 할당되어 실제로 사용되는 것
클래스 (class)
- 객체(object)를 만들기 위한 템플릿(template)
- 변수뿐만 아니라 함수도 포함할 수 있기 때문에 구조체의 상위호환으로 이해할 수 있다.
- 구조체와 클래스의 차이는 기본 접근 제한자의 차이말고는 큰 차이가 없다. ▶ 구조체: public, 클래스: private
- 클래스의 구성요소는 크게 3가지로 볼 수 있다.
- 멤버 변수(member variable): 객체 변수 또는 필드(field)라고 한다. 객체의 속성(attribute)을 변수로 적용하기 위해 사용한다.
- 메소드(method): 객체의 행위
- 생성자(constructor): 객체가 생성되기 전에 선언되며 객체를 생성하기 위한 속성을 부여하는 데 사용한다.
접근 제한자
- 접근 제한자는 정보 은닉을 위해 사용하는 기능이다.
- 클래스에서 사용할 수 있는 접근 제한자로 총 3가지 유형이 있다.
Pubilc (공개)
- 선언된 클래스 멤버가 외부로 공개되며, 해당 객체를 사용하는 프로그램의 어디에서나(다른 클래스에서도) 직접 접근이 가능하다.
- public은 주로 멤버 함수에 부여되며, 멤버 함수는 private 멤버 변수와 프로그램 사이의 인터페이스 역할을 수행한다.
Private (비공개)
- 선언된 클래스 멤버가 외부에 공개되지 않으며, 외부에서 직접 접근하는 것조차 불가능하다.
- 주로 멤버 변수가 private로 지정되며, 해당 클래스에서 public으로 지정된 멤버 함수를 통해 간접적으로 접근한다.
Protected (보호)
- 상위 클래스를 상속받는 파생 클래스에 대해서는 public처럼 취급되며, 외부에서는 private처럼 취급된다.
Default (기본)
- 접근 제한자의 종류는 아니지만, 따로 클래스에서 접근 제한자 키워드 명시를 하지 않은 멤버는 private로 설정된다.
클래스 구현 실습
클래스 정의
- 구조체는 struct 키워드를 이용하지만, 클래스는 이를 class 키워드로 대체하며, 접근 제어 지시자를 함께 사용한다.
- 대부분 다음과 같은 형태로 클래스를 정의한다.
class 클래스명{
접근제어지시자1:
datatype 멤버변수명;
....
접근제어지시자2:
멤버함수원형;
...
};
객체 선언
- 클래스를 이용하여 객체를 선언하는 방법은 다음과 같다.
클래스명 객체이름;
// Example
Pet Dog;
클래스 예제
Ex) 클래스 정의 후 인스턴스 생성하기
#include <iostream>
using namespace std;
class Pet {
private:
int age;
float weight;
string name;
public:
void set_profile(string _name, int _age, float _weight) {
cout << _name << "의 profile을 작성하였습니다." << endl;
cout << "----------------------" << endl;
age = _age;
weight = _weight;
name = _name;
}
void give_foods(float amount) {
cout << amount << "만큼의 먹이를 주었습니다." << endl;
cout << "----------------------" << endl;
weight += amount * 0.05;
}
void view_profile() {
cout << "-- 펫의 프로필 보기 --" << endl;
cout << "펫의 이름: " << name << endl;
cout << "펫의 나이: " << age << endl;
cout << "펫의 무게: " << weight << endl;
cout << "----------------------" << endl;
}
};
int main() {
Pet dog;
dog.set_profile("puppy", 3, 10.3);
dog.view_profile();
dog.give_foods(5);
dog.view_profile();
return 0;
}
puppy의 profile을 작성하였습니다.
----------------------
-- 펫의 프로필 보기 --
펫의 이름: puppy
펫의 나이: 3
펫의 무게: 10.3
----------------------
5만큼의 먹이를 주었습니다.
----------------------
-- 펫의 프로필 보기 --
펫의 이름: puppy
펫의 나이: 3
펫의 무게: 10.55
----------------------
- 모든 멤버 변수들은 private 처리하였고, 모든 멤버 함수들을 public 처리하였다.
- 인스턴스를 생성한 후 public인 인스턴스 함수를 이용하여 private인 인스턴스 변수를 조작하였다.
Ex) 클래스 외부에서 멤버 변수 정의하기
#include <iostream>
using namespace std;
class Summ {
private:
int AccuSum;
public:
void reset();
void sum(int a);
};
int main() {
Summ Sum; // 인스턴스 생성
Sum.reset(); // 값 초기화
Sum.sum(3);
Sum.sum(7);
Sum.sum(9);
}
void Summ::reset() {
cout << "값을 초기화하였습니다." << endl;
AccuSum = 0;
}
void Summ::sum(int a) {
AccuSum += a;
cout << "누적 합: " << AccuSum << endl;
}
값을 초기화하였습니다.
누적 합: 3
누적 합: 10
누적 합: 19
- 클래스 멤버 함수의 정의가 길어지는 경우, 함수를 외부로 꺼내어 정의할 수 있다.
- Summ::sum은 sum 멤버 함수가 Summ 클래스에 정의된 함수임을 의미한다.