Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 10: 클래스와 객체Topic 4: 정적 멤버와 친구 함수

Topic 4: 정적 멤버와 친구 함수 👥

🎯 학습 목표

  • static 멤버 변수와 함수의 개념을 이해할 수 있다
  • 정적 멤버와 일반 멤버의 차이점을 설명할 수 있다
  • friend 함수와 friend 클래스를 활용할 수 있다
  • 클래스 레벨의 데이터를 관리할 수 있다

🌐 Static 멤버: 모두가 공유하는 것

학교 게시판으로 이해하는 Static 📋

일반 멤버 변수는 각 학생이 가진 개인 노트와 같고, static 멤버 변수는 모든 학생이 보는 학교 게시판과 같습니다!

class Student { private: string name; // 개인 노트 (각자 다름) int studentNumber; // 개인 번호 (각자 다름) static int totalCount; // 학교 게시판 (모두 공유!) static string schoolName; // 학교 이름 (모두 같음!) public: Student(string n) { name = n; studentNumber = ++totalCount; // 전체 학생 수 증가 cout << name << " 학생 등록! 학번: " << studentNumber << endl; } // static 함수 - 객체 없이도 호출 가능! static int getTotalCount() { return totalCount; } static string getSchoolName() { return schoolName; } }; // static 멤버 변수 초기화 (클래스 밖에서!) int Student::totalCount = 0; string Student::schoolName = "코딩 고등학교";

💡 Static 멤버 실습 예제

게임 서버 관리 시스템

#include <iostream> #include <string> #include <vector> using namespace std; class GameServer { private: string playerName; int playerId; bool isOnline; // static 멤버 변수들 static int totalPlayers; // 전체 플레이어 수 static int onlinePlayers; // 현재 접속자 수 static int maxConcurrentUsers; // 최대 동시 접속자 수 static vector<string> serverLog; // 서버 로그 public: // 생성자 - 플레이어 가입 GameServer(string name) { playerName = name; playerId = ++totalPlayers; isOnline = false; cout << "🎮 [" << playerName << "] 님이 가입했습니다! (ID: " << playerId << ")" << endl; addLog(playerName + " 가입"); } // 로그인 void login() { if (!isOnline) { isOnline = true; onlinePlayers++; // 최대 동시 접속자 갱신 if (onlinePlayers > maxConcurrentUsers) { maxConcurrentUsers = onlinePlayers; } cout << "✅ [" << playerName << "] 로그인!" << endl; cout << " 현재 접속자: " << onlinePlayers << "명" << endl; addLog(playerName + " 로그인"); } else { cout << "❌ 이미 로그인 중입니다!" << endl; } } // 로그아웃 void logout() { if (isOnline) { isOnline = false; onlinePlayers--; cout << "👋 [" << playerName << "] 로그아웃!" << endl; cout << " 현재 접속자: " << onlinePlayers << "명" << endl; addLog(playerName + " 로그아웃"); } } // static 함수 - 서버 통계 static void showServerStats() { cout << "\n=== 🖥️ 서버 통계 ===" << endl; cout << "총 가입자 수: " << totalPlayers << "명" << endl; cout << "현재 접속자: " << onlinePlayers << "명" << endl; cout << "최대 동시 접속자: " << maxConcurrentUsers << "명" << endl; cout << "==================" << endl; } // static 함수 - 로그 추가 static void addLog(string message) { serverLog.push_back(message); } // static 함수 - 로그 출력 static void showLogs() { cout << "\n=== 📜 서버 로그 ===" << endl; for (const string& log : serverLog) { cout << "• " << log << endl; } cout << "==================" << endl; } }; // static 멤버 변수 초기화 int GameServer::totalPlayers = 0; int GameServer::onlinePlayers = 0; int GameServer::maxConcurrentUsers = 0; vector<string> GameServer::serverLog; int main() { // static 함수는 객체 없이도 호출 가능! GameServer::showServerStats(); // 플레이어들 생성 GameServer player1("김전사"); GameServer player2("이마법사"); GameServer player3("박도적"); // 로그인/로그아웃 테스트 player1.login(); player2.login(); player3.login(); GameServer::showServerStats(); player1.logout(); // 새 플레이어 추가 GameServer player4("최궁수"); player4.login(); GameServer::showServerStats(); GameServer::showLogs(); return 0; }

👫 Friend 함수: 특별한 친구

Friend의 개념 🤝

friend는 클래스의 private 멤버에 접근할 수 있는 특별한 권한을 가진 함수나 클래스입니다!

마치 집 열쇠를 가진 친한 친구와 같아요:

  • 일반 사람: 초인종만 누를 수 있음 (public)
  • 가족: 집 안 어디든 갈 수 있음 (같은 클래스)
  • 친한 친구: 특별히 열쇠를 줘서 들어올 수 있음 (friend)

Friend 함수 예제

#include <iostream> #include <string> #include <cmath> using namespace std; class Point { private: double x; double y; public: Point(double xPos = 0, double yPos = 0) { x = xPos; y = yPos; } void show() const { cout << "(" << x << ", " << y << ")"; } // friend 함수 선언 - 이 함수는 private에 접근 가능! friend double getDistance(const Point& p1, const Point& p2); friend class PointManager; // PointManager 클래스는 친구! }; // friend 함수 구현 - Point의 private 멤버 접근 가능 double getDistance(const Point& p1, const Point& p2) { double dx = p1.x - p2.x; // private인 x에 접근! double dy = p1.y - p2.y; // private인 y에 접근! return sqrt(dx * dx + dy * dy); } // friend 클래스 class PointManager { public: void movePoint(Point& p, double dx, double dy) { p.x += dx; // friend이므로 private 접근 가능! p.y += dy; cout << "점을 (" << dx << ", " << dy << ") 만큼 이동" << endl; } void setOrigin(Point& p) { p.x = 0; // private 멤버 직접 수정! p.y = 0; cout << "원점으로 이동" << endl; } }; int main() { Point p1(3, 4); Point p2(6, 8); cout << "점 1: "; p1.show(); cout << endl; cout << "점 2: "; p2.show(); cout << endl; // friend 함수 사용 double dist = getDistance(p1, p2); cout << "두 점 사이의 거리: " << dist << endl; // friend 클래스 사용 PointManager manager; manager.movePoint(p1, 2, 3); cout << "이동 후 점 1: "; p1.show(); cout << endl; manager.setOrigin(p2); cout << "원점 이동 후 점 2: "; p2.show(); cout << endl; return 0; }

🏢 실전 예제: 회사 직원 관리 시스템

#include <iostream> #include <string> #include <vector> using namespace std; class Employee { private: string name; int id; double salary; string department; // static 멤버 static int nextId; static int totalEmployees; static double totalSalaryBudget; public: // 생성자 Employee(string n, double s, string dept) { name = n; id = nextId++; salary = s; department = dept; totalEmployees++; totalSalaryBudget += salary; cout << "🆕 신입 사원: " << name << " (사번: " << id << ")" << endl; } // 소멸자 ~Employee() { totalEmployees--; totalSalaryBudget -= salary; } // 급여 인상 void raiseSalary(double percent) { double increase = salary * percent / 100; totalSalaryBudget -= salary; // 기존 급여 제거 salary += increase; totalSalaryBudget += salary; // 새 급여 추가 cout << "💰 " << name << "님 급여 " << percent << "% 인상!" << endl; } // static 함수 - 회사 통계 static void showCompanyStats() { cout << "\n=== 🏢 회사 현황 ===" << endl; cout << "총 직원 수: " << totalEmployees << "명" << endl; cout << "총 급여 예산: " << totalSalaryBudget << "원" << endl; if (totalEmployees > 0) { cout << "평균 급여: " << totalSalaryBudget / totalEmployees << "원" << endl; } cout << "==================" << endl; } // getter string getName() const { return name; } int getId() const { return id; } // friend 함수 선언 - HR 부서만 급여 정보 접근 가능 friend class HRDepartment; friend void auditSalary(const Employee& emp); }; // static 멤버 초기화 int Employee::nextId = 1001; int Employee::totalEmployees = 0; double Employee::totalSalaryBudget = 0; // friend 클래스 - HR 부서 class HRDepartment { public: // 급여 정보 출력 (friend이므로 private 접근 가능) void printSalaryInfo(const Employee& emp) { cout << "💼 [HR 접근] " << emp.name << "님의 급여: " << emp.salary << "원 (부서: " << emp.department << ")" << endl; } // 부서 이동 void transferDepartment(Employee& emp, string newDept) { cout << "🔄 " << emp.name << "님 부서 이동: " << emp.department << " → " << newDept << endl; emp.department = newDept; } }; // friend 함수 - 급여 감사 void auditSalary(const Employee& emp) { cout << "🔍 [감사] 사번 " << emp.id << " " << emp.name << "님 급여: " << emp.salary << "원" << endl; } int main() { // 회사 초기 상태 Employee::showCompanyStats(); // 직원 채용 Employee* emp1 = new Employee("김철수", 3000000, "개발팀"); Employee* emp2 = new Employee("이영희", 3500000, "디자인팀"); Employee* emp3 = new Employee("박민수", 4000000, "기획팀"); Employee::showCompanyStats(); // HR 부서 권한 사용 HRDepartment hr; hr.printSalaryInfo(*emp1); hr.transferDepartment(*emp2, "마케팅팀"); // 급여 인상 emp1->raiseSalary(10); // 감사 함수 사용 auditSalary(*emp3); Employee::showCompanyStats(); // 직원 퇴사 delete emp1; cout << "😢 김철수님 퇴사" << endl; Employee::showCompanyStats(); // 메모리 정리 delete emp2; delete emp3; return 0; }

📊 Static vs Non-Static 비교

특징일반 멤버Static 멤버
소속객체마다 개별클래스 전체 공유
메모리객체 생성 시 할당프로그램 시작 시 할당
접근객체를 통해 접근클래스명::멤버
this 포인터사용 가능사용 불가
초기화생성자에서클래스 외부에서

🤝 Friend 사용 시 주의사항

✅ 적절한 사용

  • 연산자 오버로딩
  • 두 클래스 간 긴밀한 협력
  • 성능이 중요한 경우

❌ 피해야 할 사용

  • 캡슐화 원칙 파괴
  • 과도한 friend 선언
  • 단순 편의를 위한 사용

💡 핵심 정리

  • static 멤버: 모든 객체가 공유하는 클래스 레벨 데이터
  • static 함수: 객체 없이 호출 가능한 클래스 함수
  • friend 함수: private 멤버에 접근 가능한 특별한 함수
  • friend 클래스: 다른 클래스의 private에 접근 가능

✅ 실습 체크리스트

🎉 Unit 10 완료!

축하합니다! 클래스와 객체의 기본을 모두 마스터했습니다! 🎊

이번 Unit에서 배운 것들:

  • ✅ 클래스의 탄생과 기본 개념
  • ✅ 캡슐화와 접근 제어
  • ✅ 멤버 함수와 this 포인터
  • ✅ 정적 멤버와 친구 함수

다음 Unit 예고

Unit 11: 생성자와 소멸자

  • 다양한 생성자 종류
  • 복사 생성자
  • 소멸자와 자원 관리
  • 이동 생성자 (C++11)

“객체지향 프로그래밍의 세계에 오신 것을 환영합니다! 🚀”

Last updated on