C++ 클래스와 객체: 캡슐화, 생성자/소멸자, 접근 제어 실전 가이드
클래스란?
C++ 클래스는 해당 데이터를 조작하는 데이터와 함수들을 단일 엔티티로 묶는 사용자 정의 데이터 타입입니다. 이를 청사진(blueprint)이라고 생각하면 됩니다: 클래스로부터 생성될 객체들의 형태와 행동을 정의합니다.
집 청사진이 문, 창문, 방 배치를 지정하듯, 클래스는 데이터 멤버들의 배치와 그들을 조작할 연산들을 기술합니다. 같은 청사진으로부터 여러 집(객체)들을 지을 수 있습니다.

위 그림에서 단일 프로토타입이 서로 다른 특징을 가진 두 개의 개별 집을 생성합니다.
이 튜토리얼에서 배울 내용:
- 클래스가 무엇이고 C++에서 왜 중요한가
- 구체적인 클래스 예제들
private과 public 접근 지정자의 역할
- 객체 생성 방법 (인스턴스화)
- 데이터 멤버 안전하게 접근하기
- 클래스 내부/외부 멤버 함수
- 생성자와 소멸자 실전
클래스 선언
클래스 선언은 간단합니다: class 키워드 뒤에 클래스 이름을 쓰고 본문을 중괄호로 감쌉니다.
문법
class className {
// 데이터 멤버
// 멤버 함수
};
- className – 클래스 식별자
- 데이터 멤버는 보통 변수로 선언
- 멤버 함수는 행동 제공
접근 지정자: private vs public
접근 지정자는 클래스 멤버의 가시성을 제어합니다.
- private – 멤버는 클래스 내부나 프렌드에서만 접근 가능
- public – 객체가 보이는 곳이면 어디서든 멤버 접근 가능
객체 생성 (인스턴스화)
객체는 클래스의 인스턴스입니다. 객체 선언은 변수 선언과 같은 패턴을 따릅니다: className objectName;
문법
className objectName;
- className – 객체가 생성될 클래스
- objectName – 새 객체 식별자
인스턴스화는 객체 메모리를 할당하고 생성자를 트리거할 수 있습니다.
데이터 멤버 접근
public 데이터 멤버는 점(.) 연산자로 접근합니다.
예제
#include <iostream>
using namespace std;
class Phone {
public:
double cost;
int slots;
};
int main() {
Phone Y6;
Phone Y7;
Y6.cost = 100.0;
Y6.slots = 2;
Y7.cost = 200.0;
Y7.slots = 2;
cout << "Cost of Huawei Y6 : " << Y6.cost << endl;
cout << "Cost of Huawei Y7 : " << Y7.cost << endl;
cout << "Number of card slots for Huawei Y6 : " << Y6.slots << endl;
cout << "Number of card slots for Huawei Y7 : " << Y7.slots << endl;
return 0;
}
출력:

왜 Getter/Setter를 사용하는가?
데이터에 직접 접근하거나 수정하면 캡슐화가 깨질 수 있습니다. getter와 setter 멤버 함수를 사용하면 제어된 접근이 가능합니다.
캡슐화 예제
#include <iostream>
using namespace std;
class ClassA {
public:
void setA(int val);
int getA() const;
private:
int a;
};
int ClassA::getA() const {
return a;
}
void ClassA::setA(int val) {
a = val;
}
int main() {
ClassA obj;
obj.setA(20);
cout << "Value of a is: " << obj.getA();
return 0;
}
출력:

Protected 멤버와 상속
Protected 멤버는 클래스 내부와 파생 클래스에서 접근 가능하여 제어된 상속을 가능하게 합니다.
예제
#include <iostream>
using namespace std;
class ParentClass {
protected:
int value;
};
class ChildClass : public ParentClass {
public:
void setId(int x) {
value = x;
}
void displayValue() {
cout << "Value is: " << value << endl;
}
};
int main() {
ChildClass c;
c.setId(21);
c.displayValue();
return 0;
}
출력:

클래스 내부 vs 외부 멤버 함수
멤버 함수는 클래스 내부에서 인라인으로 정의하거나 내부에서 선언하고 범위 해결 연산자 ::로 나중에 정의할 수 있습니다.
예제
#include <iostream>
#include <string>
using namespace std;
class Guru99 {
public:
string tutorial_name;
int id;
void printName();
void printId() {
cout << "Tutorial id is: " << id;
}
};
void Guru99::printName() {
cout << "Tutorial name is: " << tutorial_name;
}
int main() {
Guru99 guru;
guru.tutorial_name = "C++";
guru.id = 1001;
guru.printName();
cout << endl;
guru.printId();
return 0;
}
출력:

생성자와 소멸자
생성자는 객체 생성 시 초기화하고, 소멸자는 객체 파괴 직전에 정리합니다.
예제
#include <iostream>
using namespace std;
class ClassA {
public:
ClassA() {
cout << "Class constructor called" << endl;
}
~ClassA() {
cout << "Class destructor called" << endl;
}
};
int main() {
ClassA a; // 생성자 호출
int p = 1;
if (p) {
ClassA b; // 생성자 호출, 블록 끝에서 소멸자 호출
} // 'a' 소멸자 여기 호출
return 0;
}
출력:

핵심 요약
- C++은 근본적으로 객체 지향적; 클래스는 빌딩 블록
- 클래스는 데이터와 관련 함수들을 그룹화하여 재사용 가능한 청사진 생성
public, private, protected로 캡슐화 강제
- 클래스 이름 뒤에 객체 이름으로 객체 인스턴스화
- public 멤버는 점 연산자로 접근; private 데이터는 getter/setter 사용
- 멤버 함수는 인라인으로 정의하거나
::로 클래스 외부에서 정의 가능
- 생성자는 객체 초기화; 소멸자는 정리 처리