Topic 1: 생성자의 이해 🏗️
🎯 학습 목표
- 생성자의 역할과 특징을 이해할 수 있다
- 기본 생성자와 매개변수 생성자를 구분할 수 있다
- 초기화 리스트를 활용할 수 있다
- 생성자 오버로딩을 구현할 수 있다
🏠 생성자란 무엇일까요?
생성자는 객체가 태어날 때 자동으로 실행되는 특별한 함수입니다!
집 입주로 이해하는 생성자 🏡
새 집에 입주할 때를 생각해보세요:
- 🔑 열쇠 받기: 객체 생성
- 🧹 청소하기: 기본값 초기화
- 📦 짐 풀기: 매개변수로 값 설정
- 💡 전기/수도 연결: 필수 설정 완료
class House {
public:
// 생성자 - 집에 입주할 때 자동 실행!
House() {
cout << "🏠 새 집에 입주했습니다!" << endl;
// 기본 설정들
turnOnElectricity();
connectWater();
}
};📝 생성자의 특징
생성자의 규칙 ⚖️
- 클래스 이름과 동일
- 반환 타입이 없음 (void도 쓰지 않음!)
- 객체 생성 시 자동 호출
- 여러 개 만들 수 있음 (오버로딩)
class Player {
public:
// 생성자의 특징들
Player() { // 1. 클래스명과 동일
// 2. 반환 타입 없음
cout << "플레이어 생성!" << endl;
} // 3. 자동 호출됨
Player(string name) { // 4. 오버로딩 가능
cout << name << " 플레이어 생성!" << endl;
}
};🎮 기본 생성자 vs 매개변수 생성자
#include <iostream>
#include <string>
using namespace std;
class GameCharacter {
private:
string name;
int level;
int hp;
int mp;
string job;
public:
// 1. 기본 생성자 (매개변수 없음)
GameCharacter() {
name = "무명용사";
level = 1;
hp = 100;
mp = 50;
job = "초보자";
cout << "⚔️ 기본 캐릭터가 생성되었습니다!" << endl;
showInfo();
}
// 2. 매개변수 생성자 (이름만 받기)
GameCharacter(string playerName) {
name = playerName;
level = 1;
hp = 100;
mp = 50;
job = "초보자";
cout << "⚔️ " << name << " 캐릭터가 생성되었습니다!" << endl;
showInfo();
}
// 3. 매개변수 생성자 (이름과 직업 받기)
GameCharacter(string playerName, string playerJob) {
name = playerName;
job = playerJob;
level = 1;
// 직업별 초기 스탯 설정
if (job == "전사") {
hp = 150;
mp = 30;
} else if (job == "마법사") {
hp = 70;
mp = 100;
} else if (job == "궁수") {
hp = 100;
mp = 50;
} else {
hp = 100;
mp = 50;
}
cout << "⚔️ " << job << " " << name << "이(가) 생성되었습니다!" << endl;
showInfo();
}
void showInfo() {
cout << " 이름: " << name << endl;
cout << " 직업: " << job << endl;
cout << " 레벨: " << level << endl;
cout << " HP: " << hp << " / MP: " << mp << endl;
cout << "------------------------" << endl;
}
};
int main() {
cout << "=== 다양한 생성자 호출 ===" << endl;
// 기본 생성자 호출
GameCharacter char1;
// 이름만 지정
GameCharacter char2("김용사");
// 이름과 직업 지정
GameCharacter char3("이마법사", "마법사");
GameCharacter char4("박궁수", "궁수");
return 0;
}🌟 초기화 리스트 (Member Initialization List)
왜 초기화 리스트를 사용할까? 🤔
초기화 리스트는 더 효율적이고 명확한 초기화 방법입니다!
class Student {
private:
const int id; // const는 반드시 초기화 리스트로!
string name;
int& grade; // 참조도 반드시 초기화 리스트로!
double gpa;
public:
// 초기화 리스트 사용 ✅
Student(int studentId, string studentName, int& gradeRef)
: id(studentId), // const 멤버 초기화
name(studentName), // 일반 멤버 초기화
grade(gradeRef), // 참조 멤버 초기화
gpa(0.0) // 기본값 설정
{
cout << "📚 학생 정보 등록 완료!" << endl;
}
// 이렇게는 불가능! ❌
// Student(int studentId) {
// id = studentId; // 에러! const는 대입 불가
// }
};💎 실습: RPG 아이템 시스템
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
class Item {
private:
string name;
string type; // 무기, 방어구, 포션
int value; // 가격
int power; // 효과 수치
string rarity; // 일반, 희귀, 전설
public:
// 기본 생성자 - 랜덤 아이템 생성
Item() : name("미확인 아이템"),
type("미확인"),
value(0),
power(0),
rarity("일반") {
cout << "❓ 미확인 아이템을 발견했습니다!" << endl;
}
// 타입별 생성자
Item(string itemType) {
type = itemType;
rarity = "일반";
if (type == "무기") {
name = "낡은 검";
power = 10;
value = 100;
} else if (type == "방어구") {
name = "가죽 갑옷";
power = 5;
value = 80;
} else if (type == "포션") {
name = "체력 포션";
power = 50;
value = 50;
}
cout << "🎁 " << name << "을(를) 획득했습니다!" << endl;
}
// 전체 매개변수 생성자 (초기화 리스트 사용)
Item(string n, string t, int v, int p, string r)
: name(n), type(t), value(v), power(p), rarity(r) {
cout << "✨ ";
if (rarity == "전설") cout << "【전설】 ";
else if (rarity == "희귀") cout << "[희귀] ";
cout << name << "을(를) 획득했습니다!" << endl;
}
// 아이템 정보 표시
void showInfo() const {
cout << "\n=== 아이템 정보 ===" << endl;
cout << "이름: " << name << endl;
cout << "종류: " << type << endl;
cout << "등급: " << rarity << endl;
cout << "효과: " << power << endl;
cout << "가격: " << value << " 골드" << endl;
cout << "==================" << endl;
}
};
class Inventory {
private:
static const int MAX_ITEMS = 10;
Item* items[MAX_ITEMS];
int itemCount;
public:
// 생성자 - 인벤토리 초기화
Inventory() : itemCount(0) {
for (int i = 0; i < MAX_ITEMS; i++) {
items[i] = nullptr;
}
cout << "🎒 인벤토리가 생성되었습니다! (최대 "
<< MAX_ITEMS << "개)" << endl;
}
// 아이템 추가
void addItem(Item* item) {
if (itemCount < MAX_ITEMS) {
items[itemCount++] = item;
cout << "📦 인벤토리에 아이템 추가! ("
<< itemCount << "/" << MAX_ITEMS << ")" << endl;
} else {
cout << "❌ 인벤토리가 가득 찼습니다!" << endl;
}
}
// 인벤토리 표시
void showInventory() const {
cout << "\n=== 🎒 인벤토리 ===" << endl;
if (itemCount == 0) {
cout << "비어있음" << endl;
} else {
for (int i = 0; i < itemCount; i++) {
cout << i+1 << ". ";
items[i]->showInfo();
}
}
}
};
int main() {
srand(time(0));
cout << "=== RPG 아이템 시스템 ===" << endl;
// 인벤토리 생성
Inventory myInventory;
// 다양한 방법으로 아이템 생성
Item* item1 = new Item(); // 기본 생성자
Item* item2 = new Item("무기"); // 타입 지정
Item* item3 = new Item("방어구");
Item* item4 = new Item("엑스칼리버", "무기", 10000, 100, "전설");
Item* item5 = new Item("드래곤 갑옷", "방어구", 5000, 50, "희귀");
// 인벤토리에 추가
myInventory.addItem(item1);
myInventory.addItem(item2);
myInventory.addItem(item3);
myInventory.addItem(item4);
myInventory.addItem(item5);
// 인벤토리 확인
myInventory.showInventory();
// 메모리 정리
delete item1;
delete item2;
delete item3;
delete item4;
delete item5;
return 0;
}🔧 생성자 위임 (C++11)
C++11부터는 한 생성자가 다른 생성자를 호출할 수 있습니다!
class Rectangle {
private:
double width;
double height;
string color;
public:
// 전체 매개변수 생성자
Rectangle(double w, double h, string c)
: width(w), height(h), color(c) {
cout << "📐 사각형 생성 완료!" << endl;
}
// 위임 생성자 - 기본 색상 사용
Rectangle(double w, double h)
: Rectangle(w, h, "white") { // 다른 생성자 호출!
cout << " 기본 색상(white)으로 설정" << endl;
}
// 위임 생성자 - 정사각형
Rectangle(double size)
: Rectangle(size, size, "white") { // 정사각형은 가로=세로
cout << " 정사각형입니다!" << endl;
}
void showInfo() {
cout << "크기: " << width << " x " << height << endl;
cout << "색상: " << color << endl;
}
};💡 핵심 정리
- 생성자: 객체 생성 시 자동 호출되는 특별한 함수
- 기본 생성자: 매개변수가 없는 생성자
- 매개변수 생성자: 초기값을 받아 설정하는 생성자
- 초기화 리스트: 효율적이고 필수적인 초기화 방법
- 생성자 오버로딩: 다양한 방법으로 객체 생성 가능
✅ 실습 체크리스트
🚀 다음 시간 예고
다음 시간에는 복사 생성자와 대입 연산자에 대해 알아볼 거예요!
- 얕은 복사 vs 깊은 복사
- 복사 생성자 구현
- 대입 연산자 오버로딩
“생성자로 객체의 완벽한 탄생을 책임지세요! 🎂”
Last updated on