Menu
Coddy logo textTech

C++의 접근 제어자

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 34번째.

C++는 클래스 멤버에 접근할 수 있는 대상을 제어하는 세 가지 접근 지정자public, protected, private를 제공합니다. 이것들은 캡슐화의 기초를 형성합니다.

class Account {
public:
    std::string ownerName;      // 어디서나 접근 가능
    
protected:
    double interestRate;        // 이 클래스와 파생 클래스에서 접근 가능
    
private:
    double balance;             // 이 클래스 내에서만 접근 가능
};

Public 멤버는 클래스 내부, 파생 클래스, 그리고 외부 코드 등 어디에서나 접근할 수 있습니다. Private 멤버는 가장 제한적이며, 클래스 자체 내부에서만 접근할 수 있습니다. Protected는 그 중간에 위치합니다. 외부에서는 private처럼 작동하지만, 파생 클래스에서는 이 멤버들에 접근할 수 있습니다.

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // OK - 클래스 내부
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // OK - deposit은 public입니다
    // acc.balance = 500;     // 에러 - balance는 private입니다
}

기본적으로, 접근 지정자가 지정되지 않으면 클래스의 모든 멤버는 private입니다. 이는 무엇을 외부에 노출할지 명시적으로 결정하도록 유도합니다. 일반적인 관행은 데이터 멤버를 private으로 설정하고, 이들과 안전하게 상호작용할 수 있는 public 메서드를 제공하는 것입니다.

challenge icon

챌린지

쉬움

접근 지정자가 데이터 접근을 어떻게 제어하는지 보여주는 간단한 직원 관리 시스템을 만들어 보겠습니다. 일부 데이터는 완전히 비공개(private)이고, 일부는 잠재적인 하위 클래스에서 접근 가능(protected)하며, 일부는 모든 사람에게 공개(public)되는 클래스를 생성하게 됩니다.

코드를 정리하기 위해 두 개의 파일을 생성합니다:

  • Employee.h: 데이터를 적절하게 보호하기 위해 세 가지 접근 지정자를 모두 사용하는 Employee 클래스를 정의합니다:
    • Public: 직원의 name (string) — 어디서나 접근할 수 있습니다.
    • Protected: 직원의 department (string) — 클래스 내부 및 파생 클래스에서는 접근 가능하지만, 외부에서는 접근할 수 없습니다.
    • Private: 직원의 salary (double) — 클래스 내부에서만 접근할 수 있습니다.
    • 세 멤버를 모두 초기화하기 위해 name, department, salary를 매개변수로 받는 생성자
    • private인 salary 값을 반환하는 public 메서드 getSalary()
    • protected인 department 값을 반환하는 public 메서드 getDepartment()
    • 주어진 금액만큼 급여를 인상하는 public 메서드 giveRaise(double amount) (금액이 양수인 경우에만)
    • 직원의 정보를 "Name: <name>, Department: <department>, Salary: "Name: <name>, Department: <department>, Salary: $<salary>"lt;salary>" 형식으로 출력하는 public 메서드 displayInfo()
  • main.cpp: Employee 객체와 상호작용하여 접근 지정자가 어떻게 작동하는지 보여줍니다. 입력(세 개의 별도 라인)에서 직원의 이름, 부서, 급여를 읽은 후 다음을 수행합니다:
    • 입력받은 값으로 Employee 객체를 생성합니다.
    • public 멤버에 직접 접근하여 직원의 이름을 출력합니다: "Direct access - Name: <name>"
    • getter를 사용하여 부서를 출력합니다: "Via getter - Department: <department>"
    • getter를 사용하여 급여를 출력합니다: "Via getter - Salary: "Via getter - Salary: $<salary>"lt;salary>"
    • 직원에게 5000.0의 급여 인상을 적용합니다.
    • "After raise:"를 출력합니다.
    • displayInfo()를 호출하여 업데이트된 정보를 표시합니다.

<iomanip>std::fixedstd::setprecision(2)를 사용하여 모든 급여 값을 소수점 둘째 자리까지 표시하십시오. std::stod()를 사용하여 문자열로 입력받은 급여를 double로 변환하십시오.

여기서 핵심은 main에서 name에는 직접 접근할 수 있지만, departmentsalary에는 직접 접근할 수 없으며 반드시 public getter 메서드를 사용해야 한다는 점입니다. 이것이 바로 캡슐화(encapsulation)의 실제 사례입니다. 클래스가 자신의 데이터가 어떻게 접근되고 수정되는지를 제어합니다.

치트 시트

C++는 클래스 멤버에 대한 접근을 제어하기 위해 세 가지 접근 지정자(access specifiers)를 제공합니다:

  • public: 어디서나 접근 가능
  • protected: 클래스 내부 및 파생 클래스에서 접근 가능
  • private: 클래스 내부에서만 접근 가능
class Account {
public:
    std::string ownerName;      // 어디서나 접근 가능
    
protected:
    double interestRate;        // 이 클래스와 파생 클래스에서 접근 가능
    
private:
    double balance;             // 이 클래스 내부에서만 접근 가능
};

기본적으로, 지정자가 명시되지 않은 경우 클래스의 모든 멤버는 private입니다.

접근 제어를 보여주는 예제:

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // OK - 클래스 내부
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // OK - deposit은 public임
    // acc.balance = 500;     // ERROR - balance는 private임
}

권장 사항: 데이터 멤버는 private으로 설정하고, 이들과 안전하게 상호작용할 수 있는 public 메서드를 제공하세요.

직접 해보기

#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"

using namespace std;

int main() {
    // 입력 읽기
    string name;
    string department;
    string salaryStr;
    
    getline(cin, name);
    getline(cin, department);
    getline(cin, salaryStr);
    double salary = stod(salaryStr);
    
    // 급여 출력을 위한 정밀도 설정
    cout << fixed << setprecision(2);
    
    // TODO: 입력된 값으로 Employee 객체 생성
    
    // TODO: public 멤버에 직접 접근하여 직원의 이름 출력
    // 형식: "Direct access - Name: <name>"
    
    // TODO: getter 메서드를 사용하여 부서 출력
    // 형식: "Via getter - Department: <department>"
    
    // TODO: getter 메서드를 사용하여 급여 출력
    // 형식: "Via getter - Salary: $<salary>"
    
    // TODO: 직원에게 5000.0의 급여 인상 적용
    
    // TODO: "After raise:" 출력
    
    // TODO: 업데이트된 정보를 표시하기 위해 displayInfo() 호출
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨