씹어먹는 C++
5장 객체지향 프로그래밍(oop) 57p - 187p
object oriented language
추상화 ( Abstraction )
=> 컴퓨터에서 처리 할 수 있도록 현실 세계를 반영하여 함수와 변수화
캡슐화 ( Encapsulation)
=> 변수들을 외부로 보호
=> 객체의 인스턴스 변수의 값은 인스턴수 함수를 통해서 변경 ( 간접적으로 조절 )
* 사용 이유
=> 객채 내부적인 처리는 알 필요 없도록 함
=> 복잡한 객채의 일들을 내부에서 처리
variale + method
=> 변수 + 함수
객체에 정의 되면
=> instance variable + instance method
변수들과 참고 자료들로 이루어진 소프트웨어 덩이리
객체를 만들기 위한 뼈대 이자 설계도
클래스
=> member variale + member method
c++에서 클래스를 이용해 만들어진 메모리에 객체 => instance
Example code
include <iostream>
class Animal {
private:
int food;
int weight;
public:
void set_animal(int _food, int _weight) {
food = _food;
weight = _weight;
}
void increase_food(int inc) {
food += inc;
weight += (inc / 3);
}
void view_stat() {
std::cout << "이 동물의 food : " << food << std::endl;
std::cout << "이 동물의 weight : " << weight << std::endl;
}
}; // 세미콜론 잊지 말자!
int main() {
Animal animal;
animal.set_animal(100, 50);
animal.increase_food(30);
animal.view_stat();
return 0;
}
클래스 이름으로 명시
외부에서의 접근
가능 public
불가능 private < 객체내 보호를 위해 내부에서만 접근 가능
* protected < 상속인 경우에만 접근 가능
키워드 명시 없다면 private으로 설정
해당 class 내 멤버 변수는 명시 없시 사용 가능
함수의 이름이 같더라도 인자가 다르면 다른 함수라고 판단
example code
#include <iostream>
void print(int x) { std::cout << "int : " << x << std::endl; }
void print(double x) { std::cout << "double : " << x << std::endl; }
int main() {
int a = 1;
char b = 'c';
double c = 3.2f;
print(a);
print(b);
print(c);
return 0;
int : 1
int : 99 // char가 아니라 int
double : 3.2
if) 그래도 없다면 or 두 개 이상 같으면 error: ambiguous
객체 생성시 자동으로 호출되는 함수 > 객체를 초기화 해주는 역할
// 객체를 초기화 하는 역할을 하기 때문에 리턴값이 없다!
/* 클래스 이름 */ (/* 인자 */) {}
인자에 맞춰 생성자를 호출하여 객체를 생성
example code
//생성자
Date(int year, int month, int day)
//객체 생성
Date day(2011, 3, 1); // 암시적 방법 (implicit)
Date day = Date(2012, 3, 1); // 명시적 방법 (explicit)
생성자 정의를 하지 않아도 컴파일러가 자동으로 추가하여 디폴트 생성자를 호출
인자를 하나도 가지지 않는 생성자
example code
//디폴트 생성자 정의
Date() {
year = 2012;
month = 7;
day = 12;
}
//객체 선언
Date day = Date();
Date day2;
//객제가 아니라 하나의 함수로 인식 됨 *주의*
Date day3();
//명시적으로 디폴트 생성자 사용
class Test {
public:
Test() = default; // 디폴트 생성자를 정의해라
};
디폴트 생성자 제외하고 다른 인자들을 갖는 생성자 정의하여 생성자 오버로딩
클래스의 객체를 여러가지 인자타입으로 초기화 하여 객체 생성 가능
객체가 소멸 될 때 자동으로 호출 되는 함수
메모리 누수 방지로 동적 할당 delete 할 수 있도록 한다.
default destructor
소멸자가 필요 없다면 구지 적지 않아도 컴파일러가 생성
메모리 누수
객체내 동적할당 시 객체가 delete된 후 지워질 수 없어
메모리 공간에 쌓이며 필요없는 메모리 점유를 하게 된다.
소멸자가 불리는 순서 주의
전역 객체는 전체 프로그램 종료할 때 호출
지역 객체는 해당 지역이 없어질 때 호출
example code
// 소멸자
~(클래스의 이름)
Marine::~Marine() {
std::cout << name << " 의 소멸자 호출 ! " << std::endl;
if (name != NULL) {
delete[] name;
}
}
class T 의 객체 a 를 상수 레퍼런스로 받아 복사 하여 객체 생성
const이므로 내부에서 a 데이터 변경은 불가능
새로운 인스턴스 변수 초기화시 데이터 복사하여 사용
example code
// class T에서 복사 생성자
// T(const T& a);
Photon_Cannon::Photon_Cannon(const Photon_Cannon& pc) {
std::cout << "복사 생성자 호출 !" << std::endl;
hp = pc.hp;
shield = pc.shield;
coord_x = pc.coord_x;
coord_y = pc.coord_y;
damage = pc.damage;
//깊은 복사
name = new char[strlen(pc.name) + 1];
strcpy(name, pc.name);
}
//복사 생성자를 이용한 객체 생성
Photon_Cannon pc1(3, 3);
Photon_Cannon pc2(pc1);
// '=' 이용한 복사 생성자 호출
Photon_Cannon pc3 = pc2;
생성자를 호출하는 동시에 멤버 변수를 초기화
초기화 리스 사용 안 할 시
생성 먼저한 후 대입 수행 < 초기화 리스트가 효율적
const
멤버 변수 정의를 const하여 초기화 후 변경 불가능
example code
// 초기화 리스트
// (생성자 이름) : var1(arg1), var2(arg2) {}
Marine::Marine(int coord_x, int coord_y)
: coord_x(coord_x), coord_y(coord_y), hp(50), damage(5), is_dead(false) {}
클래스 하나에만 종속되는 변수
어떤 클래스의 static 멤버 변수는 프로그램이 종료 될때 소멸
클래스의 모든 객체들이 공유 하는 하나의 변수
int Marine::total_marine_num = 0;
객체가 없어도 그냥 클래스 자체에서 호출
클래스 전체에 딱 1 개 존재하는 함수
내부에 그냥 클래스의 멤버 변수들을 이용 불가능< 객체를 지정하지 않으므로
example code
// class 내 함수 선언
static void show_total_marine();
//함수 정의
void Marine::show_total_marine() {
std::cout << "전체 마린 수 : " << total_marine_num << std::endl;
}
//함수 사용시 class<T>:: (static 함수)형식으로 사용
Marine::show_total_marine();
호출하는 객체 자신을 가리키는 포인터
static 함수를 제외한 모든 멤버 함수에 정의 되어 있다
example code
Marine& Marine::be_attacked(int damage_earn) {
hp -= damage_earn;
if (hp <= 0) is_dead = true;
return *this;
}