Topic 3: 멤버 함수와 this 포인터 🎯
🎯 학습 목표
- 멤버 함수의 선언과 구현을 분리하는 방법을 익힐 수 있다
- this 포인터의 개념과 역할을 이해할 수 있다
- const 멤버 함수의 의미와 활용법을 알 수 있다
- 메서드 체이닝을 구현할 수 있다
🤔 this 포인터란?
this는 현재 객체 자신을 가리키는 특별한 포인터입니다!
거울로 이해하는 this 🪞
class Person {
private:
string name;
public:
void setName(string name) {
// 어? name이 두 개나 있네?
// 매개변수 name vs 멤버변수 name
this->name = name; // this로 구분!
// this->name: 나(객체)의 name
// name: 매개변수 name
}
void introduce() {
cout << "안녕하세요, 저는 " << this->name << "입니다!" << endl;
// this는 생략 가능: cout << name << endl;
}
};📝 멤버 함수 선언과 구현 분리
큰 프로젝트에서는 선언과 구현을 분리하는 것이 일반적입니다!
클래스 선언 (헤더 부분)
class Calculator {
private:
double result;
public:
// 함수 선언만!
Calculator(); // 생성자
void clear(); // 초기화
Calculator& add(double value); // 더하기
Calculator& subtract(double value); // 빼기
Calculator& multiply(double value); // 곱하기
Calculator& divide(double value); // 나누기
double getResult() const; // 결과 반환
void showResult() const; // 결과 출력
};멤버 함수 구현 (소스 부분)
// 생성자 구현
Calculator::Calculator() {
result = 0;
}
// clear 함수 구현
void Calculator::clear() {
result = 0;
}
// add 함수 구현 - 메서드 체이닝을 위해 자기 자신 반환
Calculator& Calculator::add(double value) {
result += value;
return *this; // 자기 자신을 반환!
}
Calculator& Calculator::subtract(double value) {
result -= value;
return *this;
}
Calculator& Calculator::multiply(double value) {
result *= value;
return *this;
}
Calculator& Calculator::divide(double value) {
if (value != 0) {
result /= value;
} else {
cout << "❌ 0으로 나눌 수 없습니다!" << endl;
}
return *this;
}
// const 멤버 함수 - 멤버 변수를 수정하지 않음
double Calculator::getResult() const {
return result;
}
void Calculator::showResult() const {
cout << "결과: " << result << endl;
}🔗 메서드 체이닝의 마법
메서드 체이닝을 사용하면 여러 메서드를 연속으로 호출할 수 있습니다!
int main() {
Calculator calc;
// 일반적인 방법
calc.add(10);
calc.multiply(2);
calc.subtract(5);
calc.showResult(); // 결과: 15
// 메서드 체이닝! 🔗
calc.clear()
.add(10) // 10
.multiply(2) // 20
.subtract(5) // 15
.add(3) // 18
.showResult();
return 0;
}🎮 실습: 게임 캐릭터 빌더
#include <iostream>
#include <string>
using namespace std;
class CharacterBuilder {
private:
string name;
string job;
int strength;
int intelligence;
int agility;
int hp;
int mp;
public:
// 생성자
CharacterBuilder() {
name = "무명";
job = "초보자";
strength = 10;
intelligence = 10;
agility = 10;
hp = 100;
mp = 50;
}
// 메서드 체이닝을 위한 setter들
CharacterBuilder& setName(string newName) {
this->name = newName;
cout << "📝 이름 설정: " << name << endl;
return *this;
}
CharacterBuilder& setJob(string newJob) {
this->job = newJob;
cout << "⚔️ 직업 선택: " << job << endl;
// 직업에 따른 보너스 스탯
if (job == "전사") {
strength += 10;
hp += 50;
} else if (job == "마법사") {
intelligence += 10;
mp += 50;
} else if (job == "도적") {
agility += 10;
}
return *this;
}
CharacterBuilder& addStrength(int value) {
this->strength += value;
cout << "💪 힘 +" << value << endl;
return *this;
}
CharacterBuilder& addIntelligence(int value) {
this->intelligence += value;
cout << "🧠 지능 +" << value << endl;
return *this;
}
CharacterBuilder& addAgility(int value) {
this->agility += value;
cout << "🏃 민첩 +" << value << endl;
return *this;
}
// const 멤버 함수 - 캐릭터 정보 출력
void showCharacter() const {
cout << "\n=== 🎮 캐릭터 정보 ===" << endl;
cout << "이름: " << name << endl;
cout << "직업: " << job << endl;
cout << "HP: " << hp << " / MP: " << mp << endl;
cout << "힘: " << strength << endl;
cout << "지능: " << intelligence << endl;
cout << "민첩: " << agility << endl;
cout << "===================" << endl;
}
// this 포인터를 명시적으로 사용하는 예제
bool isStrongerThan(const CharacterBuilder& other) const {
// this->strength는 현재 객체의 strength
// other.strength는 비교 대상의 strength
return this->strength > other.strength;
}
// 자기 자신의 주소 반환
CharacterBuilder* getAddress() {
cout << "내 주소는: " << this << endl;
return this;
}
};
int main() {
cout << "=== 캐릭터 생성 시작! ===" << endl;
// 전사 캐릭터 생성 (메서드 체이닝)
CharacterBuilder warrior;
warrior.setName("아서")
.setJob("전사")
.addStrength(15)
.addStrength(10)
.addAgility(5);
warrior.showCharacter();
// 마법사 캐릭터 생성
CharacterBuilder mage;
mage.setName("멀린")
.setJob("마법사")
.addIntelligence(20)
.addIntelligence(15);
mage.showCharacter();
// 캐릭터 비교
if (warrior.isStrongerThan(mage)) {
cout << "\n⚔️ 아서가 멀린보다 힘이 셉니다!" << endl;
} else {
cout << "\n🧙 멀린이 아서보다 힘이 셉니다!" << endl;
}
// this 포인터 주소 확인
cout << "\n=== this 포인터 확인 ===" << endl;
warrior.getAddress();
mage.getAddress();
return 0;
}🔒 const 멤버 함수의 이해
const 멤버 함수란?
const 멤버 함수는 멤버 변수를 수정하지 않겠다고 약속하는 함수입니다!
class BankAccount {
private:
double balance;
string owner;
public:
// const 함수 - 읽기만 가능
double getBalance() const {
// balance = 0; // ❌ 에러! const 함수에서는 수정 불가
return balance;
}
void showInfo() const {
cout << "계좌주: " << owner << endl;
cout << "잔액: " << balance << endl;
// owner = "해커"; // ❌ 에러!
}
// non-const 함수 - 수정 가능
void deposit(double amount) {
balance += amount; // ✅ OK!
}
};const 객체와 const 멤버 함수
int main() {
const BankAccount fixedAccount("김철수", 1000000);
// const 객체는 const 멤버 함수만 호출 가능!
fixedAccount.showInfo(); // ✅ OK! (const 함수)
fixedAccount.getBalance(); // ✅ OK! (const 함수)
// fixedAccount.deposit(100); // ❌ 에러! (non-const 함수)
BankAccount normalAccount("이영희", 500000);
normalAccount.showInfo(); // ✅ OK!
normalAccount.deposit(100); // ✅ OK!
}💡 this 포인터 활용 팁
1. 매개변수와 멤버변수 구분
class Student {
string name;
int age;
public:
void setInfo(string name, int age) {
this->name = name; // this로 명확히 구분
this->age = age;
}
};2. 객체 자신을 반환 (메서드 체이닝)
class StringBuilder {
string str;
public:
StringBuilder& append(string text) {
str += text;
return *this; // 자기 자신을 반환
}
};3. 다른 객체와 비교
bool isSameAs(const MyClass& other) {
return this == &other; // 주소 비교로 같은 객체인지 확인
}📋 멤버 함수 설계 원칙
✅ 좋은 설계
- const 가능한 함수는 const로 선언
- 메서드 체이닝이 유용한 경우 적용
- 명확한 함수 이름 사용
- 한 함수는 한 가지 일만
❌ 피해야 할 설계
- 불필요하게 복잡한 함수
- const여야 할 함수를 non-const로
- this 포인터의 과도한 사용
- 너무 많은 일을 하는 함수
💡 핵심 정리
- this 포인터: 현재 객체 자신을 가리키는 포인터
- 메서드 체이닝: *this를 반환하여 연속 호출 가능
- const 멤버 함수: 멤버 변수를 수정하지 않는 함수
- 선언과 구현 분리: 클래스명::함수명 형태로 구현
✅ 실습 체크리스트
🚀 다음 시간 예고
다음 시간에는 정적 멤버와 친구 함수에 대해 알아볼 거예요!
- static 멤버 변수와 함수
- friend 함수와 friend 클래스
- 클래스 레벨 데이터 관리
“this 포인터로 더 강력한 클래스를 만들어보세요! 🎯”
Last updated on