Menu
Coddy logo textTech

접근 제어자 심화

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

이제 세 가지 접근 지정자를 이해했으므로, 동일한 클래스의 객체가 여러 개 있을 때 이들이 어떻게 동작하는지 살펴보겠습니다. 흔한 오해 중 하나는 private이 "이 객체만"을 의미한다는 것이지만, 실제로는 "이 클래스만"을 의미합니다.

동일한 클래스의 객체는 서로의 private 멤버에 접근할 수 있습니다:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // 다른 객체의 private 멤버에 접근 - 허용됨!
        std::cout << other.secret;
    }
};

이것이 가능한 이유는 액세스 제어가 객체 수준이 아닌 클래스 수준에서 적용되기 때문입니다. readSecret 메서드는 Person 클래스의 일부이므로, 모든 Person 객체의 private 멤버에 접근할 수 있습니다. 이러한 설계 덕분에 복사 생성자나 비교 연산자와 같은 연산이 다른 객체의 내부 상태와 함께 작동할 수 있습니다.

클래스 내에서 접근 지정자를 여러 번 전환할 수도 있습니다:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // 다시 public으로
    
private:
    void privateHelper();    // 다시 private으로
};

이것이 유효한 C++이기는 하지만, 가독성을 위해 일반적으로 액세스 수준별로 멤버를 그룹화하는 것이 더 좋습니다. 대부분의 스타일 가이드는 public 멤버를 먼저 나열할 것을 권장하며(이들이 클래스 인터페이스를 형성하기 때문입니다), 그 뒤에 protected, 그 다음에 private 순으로 나열합니다.

challenge icon

챌린지

쉬움

동일한 클래스의 객체들이 서로의 private 멤버에 어떻게 접근할 수 있는지 보여주는 지갑 비교 시스템을 만들어 보겠습니다. 이는 C++ 접근 제어에 대한 핵심적인 통찰입니다. 즉, 접근 제어는 객체 수준이 아니라 클래스 수준에서 강제됩니다.

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

  • Wallet.h: 비공개 금융 데이터를 저장하지만 지갑 간 비교를 허용하는 Wallet 클래스를 정의합니다. 클래스에는 다음이 포함되어야 합니다:
    • Private 멤버: ownerName (string) 및 balance (double)
    • 소유자 이름과 초기 잔액을 인자로 받는 생성자
    • 소유자의 이름을 반환하는 public 게터 getOwnerName()
    • 이 지갑의 잔액을 다른 지갑의 private 잔액과 비교하여, 이 지갑에 돈이 더 많으면 true를 반환하는 hasMoreThan(const Wallet& other) 메서드
    • 두 지갑의 private 잔액 합계를 반환하는 combinedBalance(const Wallet& other) 메서드
    • 이 지갑에서 다른 지갑으로 돈을 옮기는 transferTo(Wallet& other, double amount) 메서드 — 두 지갑의 private 잔액을 직접 수정해야 합니다 (금액이 양수이고 이 지갑의 잔액을 초과하지 않는 경우에만).
  • main.cpp: 객체 간 private 멤버 접근을 시연합니다. 입력으로부터 두 명의 소유자 이름과 두 개의 잔액을 읽어옵니다 (네 줄: name1, balance1, name2, balance2), 그 다음:
    • 입력된 값으로 두 개의 Wallet 객체를 생성합니다.
    • combinedBalance()를 사용하여 "Combined wealth: "Combined wealth: $"lt;amount>"를 출력합니다.
    • 지갑을 비교하고 잔액이 더 높은 소유자에 대해 "<name> has more money"를 출력합니다 (이를 결정하기 위해 hasMoreThan()을 사용하세요).
    • transferTo()를 사용하여 첫 번째 지갑에서 두 번째 지갑으로 100.0을 이체합니다.
    • "After transfer:"를 출력합니다.
    • "Combined wealth: "Combined wealth: $"lt;amount>"를 다시 출력합니다 (변경되지 않아야 합니다).
    • 다시 비교하여 "<name> has more money"를 출력합니다 (결과가 바뀌었을 수 있습니다).

여기서 핵심 개념은 hasMoreThan()transferTo()와 같은 메서드가 다른 Wallet 객체의 private 멤버인 balance에 직접 접근할 수 있다는 것입니다. 게터가 필요하지 않습니다. 이는 C++의 접근 제어가 클래스 기반이기 때문에 가능합니다. 즉, Wallet 클래스 내부의 모든 코드는 모든 Wallet 객체의 private 멤버에 접근할 수 있습니다.

<iomanip>std::fixedstd::setprecision(2)를 사용하여 모든 통화 값을 소수점 이하 두 자리까지 형식화하십시오. std::stod()를 사용하여 잔액 입력을 변환하십시오.

치트 시트

C++의 접근 제어는 객체 수준이 아니라 클래스 수준에서 적용됩니다. 즉, 같은 클래스의 객체들은 서로의 private 멤버에 접근할 수 있습니다:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // 다른 객체의 private 멤버에 접근 - 허용됨!
        std::cout << other.secret;
    }
};

readSecret 메서드는 Person 클래스의 일부이기 때문에 모든 Person 객체의 private secret 멤버에 접근할 수 있습니다. 이러한 설계는 복사 생성자나 비교 연산자와 같은 연산을 가능하게 합니다.

클래스 내에서 접근 지정자를 여러 번 전환할 수 있습니다:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // 다시 public으로
    
private:
    void privateHelper();    // 다시 private으로
};

하지만 가독성을 위해 접근 수준별로 멤버를 그룹화하는 것이 더 좋은 관습입니다. 대부분의 스타일 가이드에서는 public 멤버를 먼저 나열하고, 그 다음에 protected, 마지막으로 private 멤버를 나열할 것을 권장합니다.

직접 해보기

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

using namespace std;

int main() {
    // 입력 읽기: name1, balance1, name2, balance2
    string name1, name2;
    string balanceStr1, balanceStr2;
    
    getline(cin, name1);
    getline(cin, balanceStr1);
    getline(cin, name2);
    getline(cin, balanceStr2);
    
    double balance1 = stod(balanceStr1);
    double balance2 = stod(balanceStr2);
    
    // 통화 값에 대한 출력 형식 설정
    cout << fixed << setprecision(2);
    
    // TODO: 입력된 값으로 두 개의 Wallet 객체 생성
    
    // TODO: combinedBalance()를 사용하여 합산된 자산 출력
    // 형식: "Combined wealth: $<amount>"
    
    // TODO: hasMoreThan()을 사용하여 지갑을 비교하고 누가 더 많은 돈을 가졌는지 출력
    // 형식: "<name> has more money"
    
    // TODO: transferTo()를 사용하여 첫 번째 지갑에서 두 번째 지갑으로 100.0 이체
    
    // TODO: "After transfer:" 출력
    
    // TODO: 합산된 자산을 다시 출력
    
    // TODO: 다시 비교하여 누가 더 많은 돈을 가졌는지 출력
    
    return 0;
}
quiz icon실력 점검

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

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