danbibibi
article thumbnail

1. 객체

  • instance variable(변수)와 instance method로 구성
  • 추상화(abstraction) : 컴퓨터 상에서 현실 세계를 100% 나타낼 수 없기 때문에, 적절하게 컴퓨터에서 처리할 수 있도록 바꾸는 것
  • 캡슐화(encapsulation) : 외부에서 직접 인스턴스 변수의 값을 바꿀 수 없고 항상 인스턴스 메소드를 통해서 간접적으로 조절하는 것
캡슐화의 장점
객체가 내부적으로 어떻게 작동하는지 몰라도 사용할 줄 알게 된다!!

 

2. 클래스

  • 객체의 설계도
  • 클래스를 이용해서 만들어진 객체 =  인스턴스
  • Animal:: Aniaml 클래스에 정의된 함수임을 의미
<cpp />
#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(); }; // 세미콜론 잊지 말자! void Animal::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(); // 130, 60 return 0; }
접근 지시자
private : 자기 객체 안에서만 접근 가능. 외부에서는 접근 불가능 
public : 외부에서 접근 가능

 

3. 함수 오버로딩 (Overloading)

함수의 이름이 같더라도 인자가 다르면 다른 함수라고 판단

C++ 오버로딩 과정

1. 자신과 티입이 정확히 일치하는 함수를 찾음
2. 정확히 일치하는 타입이 었는 경우 형변환을 통해 일치하는 함수를 찾음
   char, unsigned char, short -> int
   unsigned short, int -> int, unsigned int
   float -> double 
   enum -> int
3. 좀 더 포괄적인 형변환을 통해 일치하는 함수를 찾음
   임의의 숫자 타입 -> 다른 숫자 타입 ex) float -> int
    enum ->임의의 숫자 타입
    0 -> 포인터 타입, 숫자 타입
   포인터 -> void 포인터
4. 유저 정의된 타입 변환으로 일치하는 함수를 찾음

 

4. 생성자 (Constructor)

  • 클래스 이름과 이름이 같은 특별한 메소드 
  • 객체를 생성할 때 사용
  • 오버로딩 적용 가능
<cpp />
// 클래스 이름(인자) Date(int year, int month, int day)

 

4.1. 기본 생성자 (Default constructor)

  • 클래스에서 사용자가 어떠한 생성자도 명시적으로 정의하지 않았을 경우에 컴파일러가 자동으로 추가해주는 생성자
  • 직접 정의할 수도 있음
  • 명시적으로 디폴트 생성자를 사용하도록 명시할 수 있음
<cpp />
Test test; // 기본 생성자가 호출됨
<cpp />
class Test { public: Test() = default; // 디폴트 생성자를 정의해라 };
개발자가 깜빡 잊고 생성자를 정의를 안한 것인지, 아니면 정말 디폴트 생성자를 사용하고파서 이런 것인지 알 수 있음

 

4.2. 기본 복사 생성자 (default copy constructor)

  • 얕은 복사 (shallow copy)가 일어남
  • animal2의 필드가 animal1의 필드의 주소와 같은 주소를 가리킴
  • 한번 해제된 메모리는 다시 해제될 수 없음
<cpp />
Animal animal2 = animal;
깊은 복사가 필요한 경우 사용자가 직접 복사 생성자를 만들어서 사용해야 함
얕은 복사 (shallow copy) : 단순히 대입만 해주는 것
깊은 복사 (deep copy) : 메모리를 새로 할당해서 내용을 복사하는 것

 

4.3. 복사 생성자 (copy constructor)

  • Animal의 객체 animal을 상수 레퍼런스로 받음
  • = 복사 생성자 내부에서 animal의 데이터를 변경할 수 없고, 새롭게 초기화 되는 인스턴스 변수들에게만 복사 가능
  • 오직 생성 시에만 호출 됨
<cpp />
Animal::Animal(const Animal& aniaml) { // 복사 생성자 food = aniaml.food; weight = animal.weight }
인자로 받는 변수의 내용을 함수 내부에서 바꾸지 않는다면 앞에 const를 붙여 주는 것이 바람직 함

 

5. 소멸자 (Destructor)

  • C++에서 객체가 delete 될 때 자동으로 호출되는 함수
  • 동적으로 할당된 메모리는 자동으로 delete 되지 않음
  • 이런 것들이 쌓이고 쌓여 Memory Leak(메모리 누수) 이 발생함 = 소멸자 필요
  • 소멸자가 필요 없는 클래스라면 굳이 따로 작성해줄 필요는 없음
<cpp />
// ~(클래스이름) ~Test()
객체가 delete될 때 소멸자를 통해 객체 내 동적 할당된 필드를 delete 해줄 수 있음
 = 객체가 동적으로 할당받은 메모리를 해제해주는 역할

 

6. 초기화 리스트 (initializer list)

  • 생성자 호출과 동시에 멤버 변수들을 초기화 ↔ 생성을 먼저 하고 그 다음에 대입
  • 초기화 리스트를 사용하는 것이 더 효율적임
  • 상수와 레퍼런스의 경우 모두 생성과 동시에 초기화가 되어야 함
  • = 클래스 내부에 레퍼런스 변수나 상수를 넣고 싶은 경우, 초기화 리스트를 사용해서 초기화 시켜주어야함
  • 괄호 밖 - 멤버 변수, 괄호 안 - 인자
<cpp />
// (생성자 이름) : var1(arg1), var2(arg2) {} Animal::Animal : food(5), weight(30) {} Animal::Animal(int f, int w) : food(f), weight(w) {} Animal::Animal(int food, int weight) : food(food), weight(weight) {}

 

7. static 변수

  • 클래스의 모든 객체들이 공유하는 변수
  • 모든 객체들이 하나의 static 멤버 변수를 사용
  • 정의와 동시에 값이 자동으로 0으로 초기화 됨
  • 객체가 없어도 클래스 자체에서 호출 가능함
  • 생성자와 소멸자 안에 total_animal_num을 변경하도록하여 편리하게 관리할 수 있음
<cpp />
// static 변수의 초기화 int Animal::total_animal_num = 0; // 아래와 같은 방식은 불가 (const static의 경우는 가능) class Animal { static int total_animal_num = 0; ... } // 생성자 Animal::Animal(int food, int weight) : food(food), weight(weight) {total_animal_num++;} // 소멸자 ~Animal(){total_animal_num--;}
static 함수 역시 클래스 전체에 1개 존재하는 함수로, (클래스)::(static 함수) 형식으로 호출

 

8. this

객체 자신을 가리키는 포인터 역할

<cpp />
Animal& Animal::eat(int eat_num) { food -= eat_num; if (food <= 0) is_hungry = true; return *this; } // 위 코드는 아래 코드와 동일한 의미 Animal& Animal::eat(int eat_num) { this->food -= eat_num; if (this->food <= 0) this->is_hungry = true; return *this; }

 

9. 레퍼런스를 리턴하는 함수

<cpp />
#include <iostream> class A { int x; public: A(int c) : x(c) {} int& access_x() { return x; } int get_x() { return x; } void show_x() { std::cout << x << std::endl; } }; int main() { A a(5); a.show_x(); // 5 int& c = a.access_x(); c = 4; a.show_x(); // 4 int d = a.access_x(); d = 3; a.show_x(); // 4 // 아래는 오류 // int& e = a.get_x(); // e = 2; // a.show_x(); int f = a.get_x(); f = 1; a.show_x(); // 4 }

 

위 코드를 하나씩 살펴 보자.

 

<cpp />
int& c = a.access_x(); c = 4; a.show_x();
  • c는 x의 레퍼런스, 즉 x의 별명을 받음
  • c의 값을 바꾸는 것은 x의 값을 바꾸는 것과 동일함
<cpp />
a.access_x() = 3; // a.x = 3; 과 동일​
레퍼런스를 리턴하는 함수는 그 함수 부분을 원래의 변수로 치환했다고 생각해도 상관이 없음

 


<cpp />
int d = a.access_x(); d = 3; a.show_x();
  • int&이 아닌 int로 받음
  • 값의 복사가 일어나 d에는 x의 값이 들어감 (d는 x의 별명이 아닌 독립 변수)

 


<cpp />
int& e = a.get_x(); e = 2; a.show_x();
  • 오류 발생
  • 레퍼런스가 아닌 타입을 리턴하는 경우는 '값' 의 복사가 이루어지기 때문에 임시 객체가 생성됨
  • 임시객체의 레퍼런스를 가질 수 없음

 


<cpp />
int f = a.get_x(); f = 1; a.show_x();
  • 값이 복사됨
  • 실제 객체 a의 x에는 영향을 미치지 못함

 

10. const 함수

변수들의 값을 바꾸지 않고 읽기만 하는, 마치 상수 같은 멤버 함수

<cpp />
// (기존의 함수의 정의) const; int eat() const;

 

'언어 > C, C++' 카테고리의 다른 글

json-c 정리  (1) 2023.12.26
[C++] Standard Template Library - STL  (0) 2023.08.24
[C++] new, delete  (0) 2023.08.14
[C++] 참조자(reference)  (0) 2023.08.14
[C++] namespace  (0) 2023.08.11
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로