반응형
객체지향 프로그래밍

누구나 접근 가능한거 public
#include <iostream>
using namespace std;
struct Man {
public:
int age = 10;
};
int main()
{
Man kim, lee;
kim.age;
lee.age = 1;
cout << kim.age <<"\n"<< lee.age;
}

1. 캡슐화 (Encapsulation) 🎁
개념: 데이터(속성)와 그 데이터를 다루는 코드(메서드)를 하나로 묶고, 외부에서 직접 접근하지 못하도록 감싸서 보호하는 것입니다. 마치 알약의 캡슐처럼요.
예시: 자동차 🚗
운전자는 엑셀 페달을 밟아 속도를 높일 수 있지만, 엔진 내부에서 연료가 분사되고 폭발이 일어나는 복잡한 과정은 알 필요도 없고, 직접 조작할 수도 없습니다.
이처럼 엔진이라는 객체는 자신의 작동 원리(데이터와 메서드)를 캡슐화하여 보호하고, 외부에선 정해진 인터페이스(엑셀 페달)만 사용하도록 허용합니다.
2. 상속 (Inheritance) 👨👩👧
개념: 부모 객체의 속성과 기능을 자식 객체가 물려받아 그대로 사용할 수 있게 하는 것입니다. 코드를 재사용하여 중복을 줄이고 효율성을 높입니다.
예시: 동물 분류 🐈
'동물' 이라는 부모 객체가 '먹는다', '숨 쉰다', '움직인다' 와 같은 공통 기능을 가지고 있다고 합시다.
'고양이' 와 '강아지' 라는 자식 객체는 '동물'의 이 모든 기능을 자동으로 상속받습니다.
따라서 '고양이' 객체를 만들 때 '먹는다'는 기능을 다시 만들 필요가 없습니다. 자식 객체는 물려받은 기능에 '야옹 운다'나 '멍멍 짖는다' 같은 고유한 기능만 추가하면 됩니다.
3. 추상화 (Abstraction) 💡
개념: 객체의 복잡한 내부 동작을 숨기고, 사용자에게 가장 중요하고 필수적인 정보나 기능만 노출하는 것입니다.
예시: TV 리모컨 📺
우리는 리모컨의 '전원', '채널 변경', '볼륨 조절' 버튼만으로 TV를 조작합니다.
TV 내부에서 신호가 처리되고 화면에 영상이 뜨는 복잡한 과정은 사용자에게 숨겨져 있습니다.
이처럼 중요한 기능(인터페이스)만 제공하고 내부의 복잡성은 가리는 것이 추상화입니다.
4. 다형성 (Polymorphism) 🎭
개념: '하나의 형태가 여러 가지 모습(행동)을 가질 수 있다' 는 의미입니다. 같은 명령을 내리더라도 객체의 종류에 따라 다르게 동작하도록 하는 것입니다.
예시: '말하다' 기능 🗣️
'말하다(Speak)' 라는 동일한 명령이 있다고 가정합시다.
'사람' 객체에게 '말하다' 명령을 내리면 "안녕하세요" 라고 한국어로 말합니다.
'앵무새' 객체에게 '말하다' 명령을 내리면 "따라 말하기" 를 합니다.
'개' 객체에게 '말하다' 명령을 내리면 "멍! 멍!" 하고 짖습니다.
명령(메서드 이름)은 같지만, 객체(종류)에 따라 각기 다른 방식으로 동작하는 것이 다형성입니다.






클래스는 객체를 만들는 틀이다
클래스가 있어야 객체를 만들 수 있다.
클래스는 객체의 타입이다!


#include <iostream>
// 1. 클래스 (Class): 객체의 설계도입니다.
class Car {
public:
// 속성 (데이터): 객체의 상태(특성)를 정의합니다.
int speed = 0; // 모든 Car는 'speed'라는 속성을 가집니다.
// 기능 (메서드): 객체가 할 수 있는 동작을 정의합니다.
void accelerate() {
speed += 10;
}
};
int main() {
// 2. 객체/인스턴스 생성: 클래스를 이용해 메모리에 실체를 만듭니다.
// 'Car'라는 설계도를 바탕으로 'myCar'라는 실제 '인스턴스(객체)'를 만듭니다.
Car myCar;
// 3. 인스턴스 사용: 속성 접근
std::cout << "초기 속도: " << myCar.speed << " km/h" << std::endl; // 출력: 0
// 4. 인스턴스 사용: 기능 호출
// myCar 인스턴스의 'accelerate' 기능을 실행합니다.
myCar.accelerate();
// myCar의 속성값이 변경된 것을 확인합니다.
std::cout << "가속 후 속도: " << myCar.speed << " km/h" << std::endl; // 출력: 10
return 0;
}

간단한 예로 클래스를 만드는것이 캡슐화이다
부모는 슈퍼클래스라고 한다.
다형성

#include <iostream>
// 1. 부모 클래스: 'Animal'은 기본 틀을 제공합니다.
class Animal {
public:
// virtual 키워드가 다형성을 가능하게 합니다.
// "자식 클래스들이 이 기능을 다르게 구현할 거야"라고 알려줍니다.
virtual void Eat() {
std::cout << "냠냠 먹습니다." << std::endl;
}
// 소멸자에도 virtual을 붙이는 것이 좋습니다. (다형성 사용 시 메모리 관리 위함)
virtual ~Animal() {}
};
// 2. 자식 클래스 1: 'Cat'은 'Animal'을 상속받아 Eat 기능을 재정의(override)합니다.
class Cat : public Animal {
public:
void Eat() override {
std::cout << "고양이가 생선을 할짝할짝 먹습니다." << std::endl;
}
};
// 3. 자식 클래스 2: 'Dog'도 Eat 기능을 재정의합니다.
class Dog : public Animal {
public:
void Eat() override {
std::cout << "강아지가 뼈다귀를 와구와구 씹어 먹습니다." << std::endl;
}
};
int main() {
// 다형성 활용: 부모 타입 포인터에 자식 객체를 담습니다.
// 'animal'이라는 하나의 이름(Eat 함수 호출)을 사용하지만,
// 실제 객체에 따라 다른 동작(출력)을 합니다.
Animal* animal1 = new Cat(); // Animal 포인터가 Cat 객체를 가리킵니다.
Animal* animal2 = new Dog(); // Animal 포인터가 Dog 객체를 가리킵니다.
std::cout << "--- 다형성 실행 ---" << std::endl;
// 같은 'Eat()' 명령을 내렸지만,
animal1->Eat(); // Cat의 Eat()이 호출됨
animal2->Eat(); // Dog의 Eat()이 호출됨
std::cout << "--------------------" << std::endl;
delete animal1;
delete animal2;
return 0;
}

class 선언시 private public protected 이 세 가지가 있다.
#include <iostream>
using namespace std;
struct Man {
private:
int age;
double weight;
public:
void smile() {
cout << "zzz";
}
};
int main()
{
Man kim;
kim.smile();
/*kim.age = 10;
cout << kim.age;*/
}
#include <iostream>
using namespace std;
// Man은 구조체(struct)로 선언되었지만, C++에서는 class와 거의 동일하게 사용됩니다.
struct Man {
private:
// 캡슐화(Encapsulation) 원칙 적용:
// private 접근 제어자를 사용하면, 이 변수(age, weight)는
// 오직 Man 구조체(클래스) 내부의 메서드에서만 접근 가능합니다.
int age;
double weight;
public:
// public 접근 제어자: 외부에서도 호출 가능합니다.
void smile() {
cout << "zzz";
}
// 만약 age에 접근하고 싶다면, 외부에서 접근 가능한 public 함수(Getter, Setter)를 만들어야 합니다.
// int getAge() { return age; }
// void setAge(int a) { age = a; }
};
int main()
{
Man kim; // Man 구조체의 인스턴스(객체) kim을 생성합니다.
kim.smile(); // smile()은 public이므로 문제 없이 호출됩니다.
// 이 아래 주석 처리된 코드가 에러를 발생시키는 부분입니다.
/*
kim.age = 10;
// 에러 발생 이유: 'age'는 Man 구조체 내부에서 private으로 선언되었기 때문에,
// 구조체 외부(main 함수)에서 직접 접근하여 값을 할당하거나 읽으려고 하면 컴파일 에러가 발생합니다.
cout << kim.age;
// 에러 발생 이유: 위와 동일하게 private 멤버에 외부에서 접근하려는 시도입니다.
*/
return 0;
}
C++ 은 캡슐화를 중요시하기에 접근 속성을 쓰지 않으면 private로 자동 설정된다.

객체지향 언어별 접근 제어자 비교


#include<iostream> // 표준 입출력(cout 등) 기능을 사용하기 위해 필요한 헤더 파일을 포함합니다.
using namespace std; // std::cout 대신 cout처럼 짧게 사용할 수 있도록 이름 공간을 선언합니다.
// 'Man'이라는 이름의 클래스를 정의합니다. 이는 '사람' 객체를 만들기 위한 설계도입니다.
class Man {
public: // 여기서부터 선언되는 모든 멤버(속성과 기능)는 클래스 외부에서 접근 가능합니다. (가장 개방적인 접근 제어자)
int age; // 'age'는 Man 객체의 속성(나이)을 나타내는 정수형 변수입니다.
double weight; // 'weight'는 Man 객체의 속성(무게)을 나타내는 실수형 변수입니다.
// 'cry'라는 이름의 멤버 함수(메서드)를 정의합니다. 이는 객체가 수행할 수 있는 기능입니다.
void cry() {
cout << "ㅠㅠㅠㅠㅠ\n"; // 콘솔에 우는 소리를 출력하는 기능을 정의합니다.
};
// 'smile'이라는 이름의 또 다른 멤버 함수(메서드)를 정의합니다.
void smile() {
cout << "ㅎㅎ\n"; // 콘솔에 웃는 소리를 출력하는 기능을 정의합니다.
};
}; // 클래스 정의가 끝났음을 알립니다.
// 프로그램의 시작점인 main 함수입니다.
int main() {
// Man 클래스의 설계도를 바탕으로 'kim'이라는 실제 객체(인스턴스)를 메모리에 생성합니다.
Man kim;
// kim 객체의 'age' 속성에 1이라는 값을 할당합니다. (age가 public이라 외부에서 직접 접근 가능)
kim.age = 1;
// kim 객체의 'cry' 메서드(기능)를 호출합니다.
kim.cry();
// kim 객체의 'smile' 메서드(기능)를 호출합니다.
kim.smile();
// main 함수가 성공적으로 종료되었음을 운영체제에 알립니다. (생략 가능하지만 관례)
return 0;
};
게터 세터 사용
#include<iostream>
#include<string> // 문자열 사용을 위해 추가
using namespace std;
// Man 클래스는 이제 데이터를 보호하는 '캡슐' 역할을 합니다.
class Man {
private:
// 1. 데이터(속성)를 private으로 선언하여 외부 접근을 막습니다. (캡슐화)
int age;
double weight;
public:
// 생성자 (Constructor): 객체가 만들어질 때 속성을 초기화합니다.
Man(int a, double w) : age(a), weight(w) {}
// --- Getter (데이터 읽기 전용) ---
// 2. age의 값을 읽을 수 있도록 public 'Getter' 메서드를 제공합니다.
int getAge() const {
return age;
}
// --- Setter (데이터 쓰기/수정 전용, 유효성 검사 가능) ---
// 3. age의 값을 안전하게 수정할 수 있도록 public 'Setter' 메서드를 제공합니다.
void setAge(int newAge) {
if (newAge >= 0) { // 유효성 검사: 나이는 음수가 될 수 없습니다.
age = newAge;
cout << "나이가 " << age << "세로 안전하게 설정되었습니다.\n";
} else {
cout << "오류: 나이는 음수가 될 수 없습니다!\n";
}
}
// 기능(메서드)들은 public으로 유지되어 외부에서 호출 가능합니다.
void cry() {
cout << "ㅠㅠㅠㅠㅠ\n";
};
void smile() {
cout << "ㅎㅎ\n";
};
};
// ---
int main() {
// Man 객체 kim을 생성하고 나이 1세, 무게 5kg으로 초기화합니다. (생성자 사용)
Man kim(1, 5.0);
// 1. 기능 호출은 그대로 합니다.
kim.cry();
kim.smile();
// 2. 데이터 접근: 이제 kim.age = 10; 처럼 직접 접근은 불가능합니다.
// kim.age = 10; // <<-- 주석 처리: private이라 에러 발생!
// 3. Setter를 사용하여 안전하게 값을 변경합니다. (쓰기)
kim.setAge(10); // 출력: 나이가 10세로 안전하게 설정되었습니다.
kim.setAge(-5); // 출력: 오류: 나이는 음수가 될 수 없습니다! (유효성 검사 통과 못함)
// 4. Getter를 사용하여 현재 값을 읽습니다. (읽기)
cout << "현재 Kim의 나이는 " << kim.getAge() << "세 입니다.\n"; // 출력: 10
return 0;
}
자바로 변환
public class Man {
// 1. 데이터(속성)를 private으로 선언하여 외부 접근을 철저히 막습니다. (캡슐화)
private int age;
private double weight;
// 생성자 (Constructor): 객체가 생성될 때 초기값을 설정합니다.
// C++와 달리, Java에서는 클래스 이름과 동일하게 선언합니다.
public Man(int a, double w) {
this.age = a; // 'this'는 현재 객체를 지칭합니다.
this.weight = w;
}
// --- Getter (데이터 읽기 전용) ---
// 2. age의 값을 읽을 수 있도록 public 'Getter' 메서드를 제공합니다.
public int getAge() {
return age;
}
// --- Setter (데이터 쓰기/수정 전용, 유효성 검사 가능) ---
// 3. age의 값을 안전하게 수정할 수 있도록 public 'Setter' 메서드를 제공합니다.
public void setAge(int newAge) {
if (newAge >= 0) { // 유효성 검사: 나이는 음수가 될 수 없습니다.
this.age = newAge;
System.out.println("나이가 " + age + "세로 안전하게 설정되었습니다.");
} else {
System.out.println("오류: 나이는 음수가 될 수 없습니다!");
}
}
// 기능(메서드)들은 public으로 유지되어 외부에서 호출 가능합니다.
public void cry() {
System.out.println("ㅠㅠㅠㅠㅠ");
}
public void smile() {
System.out.println("ㅎㅎ");
}
}
반응형
'c프로그래밍 > Class' 카테고리의 다른 글
| C언어 7주차 Class (0) | 2025.04.21 |
|---|---|
| C언어 6주차 CLASS (0) | 2025.04.14 |
| C언어 4주차 class (0) | 2025.04.10 |
| C언어 3주차 (0) | 2025.03.24 |
| C언어 기초 2주차 (5) | 2025.03.17 |