1학년 대학 수업/C++ 프로그래밍

5주차 수업 후 과제

hawon6691 2025. 10. 2. 16:40
728x90

🧩 객체지향 프로그래밍이란?

  • 프로그램을 현실 세계의 사물(객체)처럼 바라보고, 그 사물의 속성(데이터)행동(기능)을 코드로 표현하는 방식이에요.
  • 예를 들어 자동차라는 객체를 생각해보면:
    • 속성: 색상, 브랜드, 속도
    • 기능: 가속하기, 브레이크 밟기, 경적 울리기

즉, 프로그램을 단순히 “명령어 나열”로 보는 게 아니라, 객체들의 집합과 상호작용으로 보는 거죠.


🔑 객체지향의 4가지 핵심 개념

  1. 캡슐화 (Encapsulation)
    • 데이터와 기능을 하나로 묶어 관리
    • 예: TV 내부 회로는 몰라도 리모컨 버튼만 누르면 작동
  2. 상속 (Inheritance)
    • 기존 객체의 특성을 물려받아 확장
    • 예: 자동차 클래스를 상속받아 전기차 클래스를 만들기
  3. 다형성 (Polymorphism)
    • 같은 기능이라도 객체마다 다르게 동작
    • 예: 달리기(run) → 사람은 두 발로, 자동차는 바퀴로
  4. 추상화 (Abstraction)
    • 불필요한 디테일은 감추고 중요한 것만 표현
    • 예: 운전할 때 엔진 구조는 몰라도 “엑셀 밟기”만 알면 됨

🌟 객체지향 프로그래밍의 장점

  • 재사용성: 만든 객체를 다른 프로그램에서도 활용 가능
  • 유지보수 용이: 특정 부분만 수정해도 전체 영향 최소화
  • 확장성: 새로운 기능을 쉽게 추가 가능
  • 현실 세계와 유사: 직관적이라 협업 시 이해하기 쉬움

💻 객체지향 언어 예시

  • Java ☕: 기업용 시스템에서 많이 사용
  • C++ 🎮: 게임 개발, 시스템 소프트웨어
  • Python 🐍: 데이터 분석, 웹 개발
  • C# 🖥: 마이크로소프트 생태계

👉 정리하자면, 객체지향 프로그래밍은 “현실 세계를 코드로 옮겨와 직관적이고 유지보수하기 좋은 프로그램을 만드는 방법”이에요.

 

📊 2025년 인기 객체지향 프로그래밍 언어 순위 (IEEE Spectrum 조사 기준)

순위언어특징

🥇 1위 Python 배우기 쉽고, AI·데이터 과학·웹 개발 등 다방면 활용
🥈 2위 Java 기업용 시스템, 안드로이드 앱 개발에 여전히 강세
🥉 3위 C++ 게임, 금융, 고성능 시스템에서 수요 증가
4위 C# 마이크로소프트 생태계, 게임(Unity) 개발에 강점
5위 JavaScript 웹 프론트엔드 필수 언어지만 최근 순위 하락
6위 TypeScript 대규모 웹 프로젝트에서 안정성 확보
7위 Kotlin 안드로이드 공식 언어, Java 대체로 성장
8위 Swift iOS·macOS 앱 개발에 최적화
9위 Rust 메모리 안전성·성능으로 시스템 프로그래밍에서 급부상
10위 Go 클라우드·서버 개발에서 인기 상승

🔎 해석 포인트

  • Python은 여전히 1위, 특히 AI와 데이터 분석 덕분에 압도적 인기를 유지.
  • Java는 기업 환경에서 여전히 강력한 수요.
  • C++은 AI·게임·금융 시스템 등 고성능 분야에서 다시 주목받고 있음.
  • RustGo 같은 신흥 언어도 점점 객체지향적 요소를 도입하며 성장 중.

👉 정리하면, Python·Java·C++·C#이 여전히 객체지향 언어의 핵심 축을 이루고 있고, Kotlin·Swift·Rust 같은 언어들이 차세대 주자로 부상하고 있어요.

 

🏠 집을 짓는 것과 객체지향

  • 객체 = 방
    집은 여러 개의 방으로 이루어져 있죠. 각 방은 고유한 역할(침실, 주방, 욕실)을 가지고 있어요.
  • 속성 = 방의 특징
    침실은 침대와 옷장이 있고, 주방은 냉장고와 가스레인지가 있어요.
  • 메서드(기능) = 방에서 할 수 있는 행동
    침실에서는 "잠자기()", 주방에서는 "요리하기()" 같은 행동을 할 수 있죠.
  • 집 전체(프로그램)는 방(객체)들이 모여서 완성됩니다.

🚗 자동차와 객체지향

  • 클래스 = 자동차 설계도
    자동차를 만들기 위한 청사진. "자동차는 바퀴 4개, 핸들 1개, 엔진 1개를 가진다" 같은 정의.
  • 객체(인스턴스) = 실제 자동차
    설계도를 바탕으로 만들어진 실제 차량. 예: 빨간색 소나타, 파란색 테슬라.
  • 상속 = 전기차
    기존 자동차 설계도를 물려받아, 엔진 대신 배터리를 넣는 식으로 확장.
  • 다형성 = 달리기 방식
    "달리기(run)"라는 같은 명령을 내려도, 내연기관차는 휘발유로, 전기차는 전기로 움직여요.

💳 은행 계좌와 객체지향

  • 캡슐화: 계좌의 잔액은 외부에서 직접 볼 수 없고, 입금/출금 기능을 통해서만 접근 가능.
  • 추상화: 고객은 "돈을 넣는다/뺀다"만 알면 되고, 은행 내부 시스템(데이터베이스)은 몰라도 돼요.

🌟 한 줄 정리

객체지향 프로그래밍은 “세상을 작은 부품(객체)으로 나누고, 그 부품들이 서로 협력해서 전체 시스템을 완성하는 방식”이에요.
마치 레고 블록처럼, 각 블록(객체)을 조립해서 원하는 구조물을 만드는 것과 같다고 할 수 있죠.

 

 

🎯 등장 배경 요약

1. 절차지향의 한계

  • 초기 프로그래밍은 절차지향적이었어요. 즉, “순서대로 명령을 실행”하는 방식이었죠.
  • 하지만 프로그램이 커질수록:
    • 변수와 함수가 따로 놀고
    • 코드가 재사용하기 어렵고
    • 유지보수가 복잡해졌어요

예를 들어, 레시피대로 요리하는 건 쉽지만, 요리사가 수백 명이고 메뉴가 수천 개면? 관리가 불가능하죠.


2. 현실 세계를 코드로 표현하고 싶었다

  • 사람들은 현실의 사물(예: 자동차, 사람, 은행 계좌)을 프로그램 안에서 표현하고 싶었어요.
  • 그런데 단순한 데이터 구조(struct)로는 행동(기능)까지 표현하기 어려웠죠.
  • 그래서 데이터 + 기능을 하나로 묶은 객체(Object)라는 개념이 등장했어요.

마치 “자동차”라는 객체가 있고, 그 안에 “속도”라는 데이터와 “가속하기()”라는 기능이 함께 들어있는 것처럼요.


3. 재사용성과 유지보수의 필요

  • 객체는 독립적이고 재사용 가능하게 만들 수 있어요.
  • 예를 들어, “강아지” 클래스를 만들면, 다양한 강아지 객체를 쉽게 생성할 수 있죠.
  • 코드 수정도 객체 단위로 하면 되니, 전체 시스템에 영향을 주지 않고 유지보수가 쉬워져요.

4. 캡슐화와 추상화의 장점

  • 객체는 내부 구조를 숨기고, 필요한 기능만 외부에 보여줘요.
  • 마치 TV 내부 회로는 몰라도 리모컨으로 채널만 바꾸면 되는 것처럼요.
  • 이 덕분에 복잡한 시스템을 단순하게 다룰 수 있게 되었어요.

🧠 한 줄 정리

객체지향은 “복잡한 현실을 더 잘 표현하고, 유지보수와 협업을 쉽게 하기 위해” 등장한 프로그래밍 패러다임이에요.


객체지향 언어(OOP, Object-Oriented Programming)의 주요 특징 4가지는 다음과 같아요 👍

  1. 추상화 (Abstraction)
    • 불필요한 세부사항은 감추고, 중요한 특징만 드러내는 개념입니다.
    • 예: 자동차라는 객체를 만들 때 엔진 내부의 복잡한 구조는 숨기고, 운전자가 필요한 시동, 가속, 브레이크 같은 기능만 노출합니다.
  2. 캡슐화 (Encapsulation)
    • 데이터(속성)와 메서드(기능)를 하나의 객체 안에 묶어서 외부에서 직접 접근하지 못하도록 보호합니다.
    • 접근 제한자(private, public, protected)를 활용해 정보 은닉(Information Hiding)을 실현합니다.
  3. 상속 (Inheritance)
    • 기존 클래스(부모, 슈퍼클래스)의 속성과 기능을 새로운 클래스(자식, 서브클래스)가 물려받아 재사용할 수 있습니다.
    • 코드의 재사용성을 높이고, 공통 기능을 관리하기 쉽게 합니다.
    • 예: 동물 클래스를 상속받아 강아지, 고양이 클래스를 만듦.
  4. 다형성 (Polymorphism)
    • 같은 이름의 메서드나 연산자가 상황에 따라 다르게 동작할 수 있는 성질입니다.
    • 오버로딩(Overloading, 같은 이름의 메서드 여러 개 정의)과 오버라이딩(Overriding, 부모 메서드를 자식 클래스에서 재정의)이 대표적인 예입니다.

👉 정리하면: 추상화, 캡슐화, 상속, 다형성 이 객체지향 언어의 4대 특징이에요.

 

많은 분들이 “C++은 객체지향 언어다”라고 단순히 말하지만, 정작 C++을 만든 개발자 비야네 스트롭스트룹(Bjarne Stroustrup)은 조금 다른 뉘앙스로 설명해왔습니다.


🧑‍💻 스트롭스트룹의 입장

  • 그는 C++을 “순수 객체지향 언어”라고 부르지 않았습니다.
  • 이유는 C++이 다중 패러다임 언어(multi-paradigm language)이기 때문이에요.
    • 절차지향(Procedural) 스타일도 가능
    • 객체지향(Object-Oriented) 스타일도 가능
    • 제네릭(Generic, 템플릿 기반) 프로그래밍도 가능
  • 즉, 객체지향만 강제하는 언어(Java, Smalltalk 같은)와 달리, C++은 개발자가 필요에 따라 다양한 스타일을 섞어 쓸 수 있도록 설계되었죠.

📌 왜 “객체지향 언어가 아니다”라는 말이 나왔을까?

  • C++은 C와의 호환성을 유지하면서 발전했기 때문에, 순수하게 객체지향만을 강제하지 않음.
  • 예를 들어, C 스타일의 함수와 전역 변수만으로도 프로그램을 작성할 수 있어요.
  • 그래서 일부 사람들은 “C++은 객체지향 언어가 아니라 객체지향을 지원하는 언어”라고 표현합니다.
  • 실제로 스트롭스트룹도 “C++은 객체지향을 포함한 여러 패러다임을 지원하는 언어”라고 강조했어요.

✨ 정리

  • C++ = 객체지향 언어(OOP Language)라고 불러도 틀리진 않음.
  • 하지만 창시자는 “C++은 객체지향만을 위한 언어가 아니라, 여러 패러다임을 지원하는 언어”라고 설명했어요.
  • 따라서 “C++은 객체지향 언어가 아니다”라는 말은 맥락상 ‘순수 객체지향 언어가 아니다’라는 의미로 이해하는 게 맞습니다.

위에 그림은 C언어 방식.

아래에 그림은 C++ 방식.

 

 

자료와 함수를 하나로 묶으면 객체가 되고 그 객체가 모이면 시스템/프로그램 이 되고 이 시스템/프로그램 들이 모이면 소프트웨어 생택계 가 됩니다.


🧩 객체가 모이면?

  1. 객체 → 클래스 기반의 인스턴스들
    • 같은 설계도(클래스)로부터 여러 객체가 만들어져요.
    • 예: 자동차 클래스 → 빨간 자동차, 파란 자동차, 전기 자동차 객체들.
  2. 여러 객체 → 시스템(프로그램)
    • 객체들이 서로 메시지를 주고받으며 협력할 때, 하나의 프로그램이 완성돼요.
    • 예: 은행 프로그램
      • 고객 객체, 계좌 객체, ATM 객체가 서로 상호작용 → 은행 시스템 완성.
  3. 여러 시스템 → 소프트웨어 생태계
    • 프로그램들이 모여 더 큰 서비스나 플랫폼을 형성해요.
    • 예:
      • 결제 시스템 + 배송 시스템 + 상품 관리 시스템 → 온라인 쇼핑몰
      • 로그인 서비스 + 게시판 서비스 + 알림 서비스 → SNS 플랫폼

🔎 비유로 이해하기

  • 객체 = 레고 블록 하나
    (데이터와 기능이 합쳐진 작은 단위)
  • 객체들이 모임 = 레고 구조물
    (집, 자동차, 비행기 같은 완성품)
  • 여러 구조물이 모임 = 레고 마을
    (여러 프로그램이 모여 하나의 거대한 소프트웨어 생태계)

✨ 정리

  • 자료 + 함수 = 객체
  • 객체 + 객체 = 프로그램(시스템)
  • 프로그램 + 프로그램 = 더 큰 소프트웨어 생태계

즉, 객체는 작은 단위지만, 모이고 협력하면서 현실 세계를 닮은 복잡한 시스템을 만들어내는 거예요.


🧩 클래스(Class)

  • 정의: 객체를 만들기 위한 설계도
  • 특징: 속성(변수)과 행동(메서드)을 정의
  • 비유: 아파트 설계도, 자동차 도면
  • 예시 (Java):
    class Car {
        String color;
        void drive() { System.out.println("달린다!"); }
    }
    

🚗 객체(Object)

  • 정의: 클래스를 기반으로 실제로 만들어진 실체
  • 특징: 메모리에 존재하며, 클래스에서 정의한 속성과 기능을 가짐
  • 비유: 설계도로 지어진 실제 아파트 한 채, 실제 도로 위의 자동차
  • 예시:
    Car myCar = new Car(); // myCar는 객체
    myCar.color = "red";
    myCar.drive();
    

🔎 인스턴스(Instance)

  • 정의: 특정 클래스에서 생성된 객체를 지칭할 때 쓰는 용어
  • 특징: “이 객체는 Car 클래스의 인스턴스다”처럼 소속을 강조할 때 사용
  • 비유: “이 아파트는 삼성 아파트 설계도의 인스턴스다”
  • 예시:
    • myCar는 Car 클래스의 인스턴스
    • 즉, 객체라는 일반 개념 안에서, 어떤 클래스에서 만들어졌는지를 명확히 할 때 “인스턴스”라고 부름

📊 차이 요약

구분클래스(Class)객체(Object)인스턴스(Instance)

의미 설계도, 틀 설계도로 만들어진 실체 특정 클래스에서 생성된 객체
존재 추상적 개념 메모리에 존재 객체의 소속을 강조하는 용어
비유 자동차 설계도 실제 자동차 “이 자동차는 Car 설계도의 인스턴스”

✨ 정리하면:

  • 클래스는 설계도,
  • 객체는 그 설계도로 만들어진 실체,
  • 인스턴스는 “객체가 어떤 클래스에서 나왔는지”를 강조할 때 쓰는 말이에요.


🏠 집 비유로 이해하기

개념설명집 비유

클래스(Class) 설계도, 즉 집을 짓기 위한 청사진 “아파트 설계도”
객체(Object) 설계도를 바탕으로 실제로 만들어진 실체 실제로 지어진 아파트 한 채
인스턴스(Instance) 특정 클래스에서 생성된 객체임을 강조할 때 쓰는 용어 “이 아파트는 ‘아파트 설계도(Class)’로부터 만들어진 인스턴스다”

🔎 차이의 핵심

  • 객체는 그냥 “존재하는 실체”를 가리켜요.
    → “저기 보이는 집은 객체다.”
  • 인스턴스는 “그 객체가 어떤 클래스에서 나왔는지”를 강조할 때 쓰는 말이에요.
    → “저 집은 ‘아파트 설계도(Class)’의 인스턴스다.”

즉, 모든 인스턴스는 객체지만, 객체라는 말이 항상 인스턴스라는 의미를 강조하는 건 아니에요.


✨ 정리

  • 객체(Object) = 현실에 존재하는 실체 (집 자체)
  • 인스턴스(Instance) = 그 객체가 특정 클래스(설계도)에서 만들어졌음을 강조하는 표현 (집이 ‘아파트 설계도’에서 지어졌다는 사실)

 

 

 

 


🧩 다형성(Polymorphism)이란?

  • 하나의 인터페이스(같은 이름의 메서드)로 여러 객체가 각기 다른 동작을 할 수 있는 성질.
  • 즉, “같은 메시지를 보내도 객체에 따라 다르게 반응한다”는 개념이에요.

🔑 다형성의 종류

  1. 정적 다형성 (Static Polymorphism)
    • 컴파일 시점에 어떤 메서드가 호출될지 결정됨
    • 구현 방식: 메서드 오버로딩 (Method Overloading)
    • 예: add(int a, int b) 와 add(double a, double b) → 같은 이름, 다른 매개변수
  2. 동적 다형성 (Dynamic Polymorphism)
    • 실행 시점에 어떤 메서드가 호출될지 결정됨
    • 구현 방식: 메서드 오버라이딩 (Method Overriding)
    • 예: makeSound() → Dog는 “멍멍”, Cat은 “야옹”

🚗 예시 (C++ 코드)

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void makeSound() { cout << "동물이 소리를 냅니다." << endl; }
};

class Dog : public Animal {
public:
    void makeSound() override { cout << "멍멍!" << endl; }
};

class Cat : public Animal {
public:
    void makeSound() override { cout << "야옹!" << endl; }
};

int main() {
    Animal* a1 = new Dog();
    Animal* a2 = new Cat();

    a1->makeSound(); // 멍멍!
    a2->makeSound(); // 야옹!

    delete a1;
    delete a2;
}

👉 같은 makeSound() 호출이지만, 객체의 타입에 따라 다른 결과가 나오는 게 다형성이에요.


🌟 다형성의 장점

  • 유연성: 새로운 객체를 추가해도 기존 코드 수정 최소화
  • 재사용성: 같은 인터페이스로 다양한 객체를 다룰 수 있음
  • 가독성: 코드가 더 직관적이고 깔끔해짐
  • 확장성: 기능 추가가 쉬움

✨ 한 줄 정리

Polymorphism = “하나의 인터페이스, 여러 개의 구현”
즉, 같은 명령을 내려도 객체마다 다르게 반응하는 능력이에요.



C++에서 클래스(class) 안에서 “자료 은닉(Information Hiding)”을 할 때 핵심은 접근 지정자(access specifier)를 통해 멤버(변수·함수)의 가시성을 제어하는 거예요. 즉, 자료형 자체가 특별히 달라지는 게 아니라, 같은 자료형이라도 접근 권한을 어떻게 주느냐에 따라 은닉이 달라집니다.


🧩 클래스에서 자료 은닉을 위한 접근 지정자 종류

접근 지정자의미기본 적용 대상특징

private 클래스 내부에서만 접근 가능 클래스 멤버 변수/함수 외부에서 직접 접근 불가 → 캡슐화의 핵심
protected 클래스 내부 + 상속받은 자식 클래스에서 접근 가능 상속 관계 외부에서는 접근 불가, 상속 구조에서만 열어줌
public 어디서든 접근 가능 인터페이스 역할 외부에서 사용할 수 있는 함수(메서드) 제공

🔎 예시 코드

#include <iostream>
using namespace std;

class BankAccount {
private:   // 은닉된 데이터
    int balance;

public:    // 외부에 공개된 인터페이스
    BankAccount(int money) : balance(money) {}

    void deposit(int amount) { balance += amount; }
    void withdraw(int amount) { if(balance >= amount) balance -= amount; }
    int getBalance() { return balance; }
};

int main() {
    BankAccount acc(1000);
    acc.deposit(500);
    cout << acc.getBalance() << endl; // 1500 출력

    // acc.balance = 9999;  // ❌ private라서 직접 접근 불가
}

👉 여기서 balance는 private으로 은닉되어 외부에서 직접 접근할 수 없고, deposit(), withdraw(), getBalance() 같은 public 메서드를 통해서만 다룰 수 있어요.


📌 정리

  • C++ 클래스에서 자료 은닉은 자료형의 종류가 아니라 접근 지정자(private, protected, public)로 구분됨.
  • 일반적으로 멤버 변수는 private, 멤버 함수(인터페이스)는 public으로 두어 캡슐화를 구현.
  • 필요할 경우 protected를 사용해 상속 관계에서만 접근 허용.


각 언어마다 객체지향(Object-Oriented Programming, OOP)을 표현하는 방식과 용어가 조금씩 달라요. 같은 개념이라도 언어 철학과 문법에 따라 다르게 불리거나 구현됩니다. 정리해드릴게요.


🧩 언어별 객체지향 용어 비교

개념CC++JavaScriptJavaPython

클래스(Class) 없음 (struct만 존재, 함수와 데이터 분리) class 키워드로 정의 ES6부터 class 문법 제공 (실제로는 prototype 기반) class 키워드로 정의 (순수 OOP 지향) class 키워드로 정의
객체(Object) 구조체 변수(데이터 묶음) 클래스 인스턴스 객체 리터럴 {} 또는 new Class() 클래스 인스턴스 클래스 인스턴스, 모든 것이 객체
인스턴스(Instance) 없음 (구조체 변수는 단순 데이터 묶음) new로 생성된 객체 new 키워드로 생성된 객체 new로 생성된 객체 클래스 호출로 생성된 객체
상속(Inheritance) 없음 class Child : public Parent extends 키워드 (ES6) 또는 prototype 체인 extends 키워드 클래스 정의 시 괄호 안에 부모 클래스 지정
다형성(Polymorphism) 함수 오버로딩 불가 함수 오버로딩, 가상 함수(virtual) 동적 타이핑 기반, 오버라이딩 가능 오버로딩(제한적), 오버라이딩 지원 오버라이딩 지원, 오버로딩은 기본적으로 없음
캡슐화(Encapsulation) 없음 (모든 멤버 public) private, protected, public 원래는 접근제어자 없음 → #(private 필드) 추가됨 private은 없고, public, protected, default 접근제어자 접근제어자 없음, _name, __name 네이밍 컨벤션으로 은닉
추상화(Abstraction) 없음 추상 클래스(순수 가상 함수) 인터페이스 없음, duck typing abstract class, interface 추상 클래스(abc 모듈), duck typing

🔎 핵심 차이 포인트

  • C: 절차지향 언어. 객체지향 개념 자체가 없음. 구조체는 단순 데이터 묶음.
  • C++: 다중 패러다임 언어. 절차지향 + 객체지향 + 제네릭 모두 지원.
  • JavaScript: 원래는 프로토타입 기반 언어. ES6 이후 class 문법이 추가되었지만 내부적으로는 prototype 체인.
  • Java: 순수 객체지향 언어에 가까움. 모든 코드가 클래스 안에 존재.
  • Python: “모든 것이 객체”라는 철학. 접근제어자가 없고, 네이밍 규칙으로 은닉을 표현.

✨ 정리

  • C는 객체지향 개념이 아예 없고,
  • C++은 객체지향을 지원하지만 강제하지 않으며,
  • JavaScript는 prototype 기반이지만 class 문법을 흉내내고,
  • Java는 객체지향을 강하게 강제하는 언어,
  • Python은 유연하게 객체지향을 지원하면서도 duck typing 철학을 강조합니다.


getter와 setter는 객체지향 프로그래밍에서 캡슐화(encapsulation)를 구현할 때 가장 기본적으로 쓰이는 메서드예요.
즉, 멤버 변수를 private으로 숨기고, 외부에서는 getter(읽기)setter(쓰기)를 통해서만 접근하게 만드는 방식입니다.


🧩 기본 개념

  • getter: 멤버 변수의 값을 읽어오는 함수
    • 보통 get변수명() 형태
  • setter: 멤버 변수의 값을 설정하는 함수
    • 보통 set변수명(값) 형태

🚗 예제 (C++)

#include <iostream>
#include <string>
using namespace std;

class Person {
private:
    string name;   // 외부에서 직접 접근 불가
    int age;

public:
    // setter (값 설정)
    void setName(string n) {
        name = n;
    }
    void setAge(int a) {
        if (a >= 0) age = a;   // 유효성 검사 가능
    }

    // getter (값 읽기)
    string getName() {
        return name;
    }
    int getAge() {
        return age;
    }
};

int main() {
    Person p;

    // setter 사용 → 값 설정
    p.setName("홍길동");
    p.setAge(25);

    // getter 사용 → 값 읽기
    cout << "이름: " << p.getName() << endl;
    cout << "나이: " << p.getAge() << endl;

    return 0;
}

📌 실행 결과

이름: 홍길동
나이: 25

🔎 왜 getter/setter를 쓰나?

  1. 데이터 은닉: 멤버 변수를 private으로 숨김
  2. 유효성 검사: setter 안에서 잘못된 값이 들어오는 걸 막을 수 있음
    • 예: 나이가 음수면 무시
  3. 유연성: 내부 구현을 바꿔도 외부 코드는 그대로 유지 가능

✨ 정리하면:

  • getter는 값을 안전하게 꺼내는 창구,
  • setter는 값을 안전하게 넣는 창구예요.
  • 이 두 가지를 통해 클래스 내부 데이터는 보호되고, 외부에서는 안전하게 접근할 수 있습니다.

 

 


각 언어마다 접근 지정자(access modifiers)의 종류와 기본 동작이 조금씩 다릅니다. 한눈에 비교할 수 있도록 표로 정리해드릴게요.


🧩 언어별 Access Modifiers 비교

언어접근 지정자설명기본 접근 수준

C++ public 어디서든 접근 가능 class는 기본 private, struct는 기본 public
  protected 같은 클래스 + 상속받은 자식 클래스에서 접근 가능  
  private 같은 클래스 내부에서만 접근 가능  
Java public 모든 패키지/클래스에서 접근 가능 클래스 멤버는 기본 default (package-private)
  protected 같은 패키지 + 다른 패키지의 자식 클래스 접근 가능  
  default (package-private) 접근 지정자 생략 시, 같은 패키지 내에서만 접근 가능  
  private 같은 클래스 내부에서만 접근 가능  
PHP public 어디서든 접근 가능 기본 public
  protected 같은 클래스 + 상속받은 자식 클래스 접근 가능  
  private 같은 클래스 내부에서만 접근 가능  
C# public 어디서든 접근 가능 클래스 멤버는 기본 private
  protected 같은 클래스 + 상속받은 자식 클래스 접근 가능  
  private 같은 클래스 내부에서만 접근 가능  
  internal 같은 어셈블리(프로젝트) 내에서만 접근 가능  
  protected internal 같은 어셈블리 + 상속받은 자식 클래스 접근 가능  
  private protected 같은 어셈블리 내에서 상속받은 자식 클래스만 접근 가능 (C# 7.2+)  

🔎 핵심 차이

  • C++: class는 기본 private, struct는 기본 public
  • Java: default(package-private)라는 독특한 접근 수준 존재
  • PHP: 단순하게 public/protected/private만 지원
  • C#: internal, protected internal, private protected 등 가장 세밀한 제어 가능

✨ 정리하면:

  • C++/PHP는 단순한 3단계(public/protected/private)
  • Java는 패키지 개념을 반영한 default가 추가
  • C#은 어셈블리 개념까지 포함해 가장 다양한 접근 제어자를 제공

 


C++에서 privateprotected는 둘 다 캡슐화를 위한 접근 지정자지만, 실제 현업 코드나 교재 예제에서 더 많이 쓰이는 건 private입니다.


🧩 이유 정리

1. private이 기본값

  • class에서 접근 지정자를 생략하면 자동으로 private이 됩니다.
  • 따라서 특별히 상속을 고려하지 않는 한, 멤버 변수는 대부분 private으로 선언하는 게 관례예요.

2. 캡슐화 원칙

  • 객체지향의 핵심은 데이터 은닉 → 멤버 변수는 외부에서 직접 접근하지 못하게 막고, getter/setter 같은 public 메서드를 통해서만 접근하도록 하는 게 일반적입니다.
  • 이 목적에 가장 잘 맞는 게 private.

3. protected의 용도

  • protected는 상속 관계에서 자식 클래스가 부모의 멤버에 접근할 수 있도록 열어줄 때 사용합니다.
  • 하지만 실제로는 “멤버 변수까지 상속받은 클래스에서 직접 건드리게 하는 것”은 권장되지 않아요.
  • 대신 부모 클래스의 public 메서드를 통해 간접적으로 다루는 게 더 안전한 설계입니다.
  • 그래서 protected는 함수(메서드)를 상속 구조에서 재사용할 때 주로 쓰이고, 변수에는 잘 안 씁니다.

📌 정리

  • 실무/교재에서 가장 많이 쓰이는 건 private
    • 멤버 변수는 거의 항상 private
    • 외부 접근은 public 메서드로 제한
  • protected는 상속 구조에서만 제한적으로 사용
    • 주로 “자식 클래스가 오버라이드할 수 있도록” 함수에 붙임
    • 멤버 변수에는 잘 쓰지 않음

✨ 한 줄로 말하면:
👉 C++에서는 private이 기본이자 가장 많이 쓰이고, protected는 상속 상황에서만 가끔 등장하는 조연이에요.


 

#include <iostream>
#include <string>
using namespace std;

class Creature
{
protected: //protected는 '자식만' 접근 가능
	virtual void type() {}
};

class Dog : Creature { //접근지정자가 없으면 자동으로 private으로 지정됨(기본이 private, strcut 는 반대임)
private: //private은 외부에서 접근 불가
	int _age;
	double _weight;
public: //public은 외부에서 접근 가능
	Dog() : _age(), _weight() {}
	~Dog() {}

	void type() override { cout << "dogType\n"; }

	void smile() { cout << "흐흐흐흐\n"; }
	void cry() { cout << "ㅠㅠㅠㅠ\n"; }

	void setAge(int age) { this->_age = age; }
	int getAge() { return this->_age; }
	void setWeight(double weight) { this->_weight = weight; }
	double getWeight() { return this->_weight; }
};

int main() {
	Dog* jackTheReaper = new Dog();

	jackTheReaper->setAge(10);
	jackTheReaper->setWeight(1.2);

	jackTheReaper->type();

	cout << jackTheReaper->getAge() << "\n" << jackTheReaper->getWeight() << "\n";

	delete jackTheReaper;

	return 0;
}

 

#include <iostream>
#include <string>

class Man {
private:
	int _age;
	double _weight;
public:
	void smile() { std::cout << "ㅎㅎㅎ\n"; }
	void cry() { std::cout << "ㅠㅠㅠ\n"; }
};

int main() {
	Man seo;
	seo.cry();
	seo.smile();

	return 0;
}

 

👍 올려주신 코드를 하나씩 분석해보고, 객체지향적으로 더 보강할 수 있는 부분을 알려드릴게요.


🧩 코드 분석

class Man {
private:
    int _age;
    double _weight;
public:
    void smile() { std::cout << "ㅎㅎㅎ\n"; }
    void cry() { std::cout << "ㅠㅠㅠ\n"; }
};
  • 클래스 정의
    • Man이라는 클래스를 정의.
    • private 멤버: _age, _weight → 외부에서 직접 접근 불가.
    • public 멤버 함수: smile(), cry() → 객체의 행동을 표현.
int main() {
    Man seo;
    seo.cry();
    seo.smile();
    return 0;
}
  • 객체 생성
    • Man seo; → 스택에 seo라는 객체 생성.
  • 메서드 호출
    • seo.cry(); → "ㅠㅠㅠ" 출력
    • seo.smile(); → "ㅎㅎㅎ" 출력

✅ 현재 코드의 특징

  • 장점
    • 클래스 문법을 잘 사용했고, 객체 생성 및 메서드 호출이 정상 동작.
    • private 멤버 변수를 선언해 캡슐화의 기본 구조를 갖춤.
  • 아쉬운 점
    • _age, _weight 멤버 변수를 선언했지만 사용하지 않음.
    • 생성자/소멸자가 없음 → 객체 초기화가 불완전할 수 있음.
    • getter/setter가 없어 외부에서 나이, 몸무게를 안전하게 다룰 수 없음.

🔧 개선할 수 있는 부분

1. 생성자(Constructor) 추가

객체 생성 시 나이와 몸무게를 초기화할 수 있도록 하면 좋아요.

Man(int age, double weight) : _age(age), _weight(weight) {}

2. Getter / Setter 추가

캡슐화 원칙에 따라 멤버 변수는 private으로 두고, 접근은 메서드로만.

void setAge(int age) { _age = age; }
int getAge() const { return _age; }

void setWeight(double weight) { _weight = weight; }
double getWeight() const { return _weight; }

3. 정보 출력 메서드

객체 상태를 확인할 수 있는 메서드 추가.

void showInfo() {
    std::cout << "나이: " << _age << ", 몸무게: " << _weight << std::endl;
}

🚀 개선된 코드 예시

#include <iostream>
#include <string>
using namespace std;

class Man {
private:
    int _age;
    double _weight;
public:
    // 생성자
    Man(int age, double weight) : _age(age), _weight(weight) {}
    ~Man() {}

    // 행동
    void smile() { cout << "ㅎㅎㅎ\n"; }
    void cry() { cout << "ㅠㅠㅠ\n"; }

    // Getter / Setter
    void setAge(int age) { _age = age; }
    int getAge() const { return _age; }

    void setWeight(double weight) { _weight = weight; }
    double getWeight() const { return _weight; }

    // 정보 출력
    void showInfo() {
        cout << "나이: " << _age << ", 몸무게: " << _weight << endl;
    }
};

int main() {
    Man seo(25, 70.5); // 생성자로 초기화
    seo.cry();
    seo.smile();
    seo.showInfo();

    return 0;
}

📌 정리

  • 지금 코드도 잘 동작하지만, 객체지향적으로는 생성자, getter/setter, 정보 출력 메서드를 붙이면 더 완성도가 높아집니다.
  • 이렇게 하면 Man 클래스가 단순히 행동만 하는 게 아니라, 상태(나이, 몸무게) + 행동(웃기, 울기)를 모두 가진 진짜 객체다운 클래스가 돼요.

 

728x90

'1학년 대학 수업 > C++ 프로그래밍' 카테고리의 다른 글

5주차 예습 과제  (0) 2025.09.30
4주차 수업 후 과제  (0) 2025.09.25
4주차 예습 과제  (0) 2025.09.22
3 주차 수업 요약  (1) 2025.09.18
3주차 예습 과제  (0) 2025.09.13