본문 바로가기

문과 코린이의, [C. C++] 기록/C++ 이론

[문과 코린이의 IT 기록장] C,C++ - 클래스, 생성자( 클래스에 대한 이해, 생성자, 매개변수에 따른 생성자 오버로딩, 이니셜라이저(:) 이용, 소멸자 )

반응형

[문과 코린이의 IT 기록장] C,C++ - 클래스, 생성자

( 클래스에 대한 이해, 생성자, 매개변수에 따른 생성자 오버로딩, 이니셜라이저(:) 이용, 소멸자 )


 1. 클래스에 대한 이해
ex )

cf ) 61행에, month == 12? 12 : month & 12에 대한 이해
? : - 삼항연산자
12 (참, 거짓을 판단할 변수) ? 12(참 일때 사용할 값) : month & 12(거짓일 때 사용할 값)

[ 이 코드에서 클래스 관려해 중요시 봐야할 부분 ]
1. 함수의 정의와 몸통이 분리되어 있다.
ex. 클래스 내부에,
class Date{
...
void Setdate(int year_, int month_, int Date_)
...
};
클래스 외부에, 
Void Date :: SetDate{ ... }
이렇게 분리되어 있는 모습을 볼 수 있다.

- Date::을 함수 이름 밖에 붙여주게 되면, 이 함수가 Date 클래스의 정의된 함수라는 이름을 부여하게 된다.


2. main함수 이해
Int main(){
Date day; // 인스턴스 생성
day.SetDate(2011,3,1); // SetDate함수로 인스턴스 초기화
day.ShowDate(); // 제대로 인스턴스가 초기화되었는지 확인

day.AddDay(30); // 30일 증가시키기
day.ShowDate(); // 새로운 날짜 확인
...
}


- 객체생성과 초기화를 분리할 수도 있지만, 프로그래머들은 생성과 초기화를 동시에 할 수 있도록 만들 수 있다.
- 이와 같이, 생성한 객체를 초기화하는 과정을 동시에 할 수 있도록 돕는 언어장치가 있는데 바로, 이를 생성자(constructor)라고 한다.





 2. 생성자
: 객체를 생성하고, 객체의 맴버변수 초기화를 동시에 할 수 있도록 하는 것.
* 초기화란? ) 초기값, 가장 먼저 가지게 되는 입력값. (기준값)

ex ) 위의 클래스의 코드를, 생성자로 한번 바꿔서 작성해보자.

- 생성자는 기본적으로 객체 생성시 자동으로 호출되는 함수라고 할 수 있다. 이 때, 자동으로 호출되면서 객체를 초기화해주는 역할을 담당하게 된다.

1) 생성자 정의 방법
클래스 이름 (인자) {}
ex ) Date(int year_, int month_, int day_) {}


2) 생성자 호출 방법
a. 암시적 방법
클래스이름 객체이름(인자);
ex ) Date day(2011, 3, 1);
- Date클래스의 day객체를 만들면서, 생성자 Date를 호출한다. 따라서 Date의 객체를 생성할 때 생성자의 인자에 각각 2011, 3, 1을 전달하며 객체를 생성하게 된다.

b. 명시적 방법
클래스이름 객체이름 = 클래스이름(인자);
ex ) Date day = Date(2011, 3, 1);


3) 생성자의 특징
1. 클래스의 이름과 함수의 이름이 동일하다.
2. 반환형(return)이 선언되지 않고, 반환되지도 않는다.
3. 객체 생성시 반드시 한 번만 호출된다.
4. 생성자도 함수이기 때문에 오버로딩, 디폴트 값이 설정 가능하다.





 3. 매개변수에 따른, 생성자 오버로딩
ex )

1) 디폴트 생성자 (Defalt Constructor)
- 우리는 (1.클래스에 대한 이해)에서, 생성자를 정의해주지 않았음에도 불구하고 'Date day'가 실행되어 객체가 생성된 것을 볼 수 있었다.
- 이는 생성자를 정의하지 않아도, 기본적으로 호출되는 디폴트 생성자(Defalt Constructor)가 존재하기 때문이다.
* 디폴트 생성자란? : 클래스에서 사용자가 어떠한 생성자도 명시적으로 정의하지 않았을 경우에, 컴파일러가 자동으로 추가해주는 생성자이다. (매개변수가 없는 생성자)

ex ) SimpleClass(){ // 디폴트 생성자 (매개변수가 없는, 기본생성자)
num1 = 0;
num2 = 0;
}

a. 호출 방법
SimpleClass sim;

// 절대로 인자가 없는 생성자를 호출하기 위해서 SimpleClass sim();와 같이 하면 안된다. 이 문장은 SimpleClass형을 반환하는 함수, sim을 정의한 문장이다.

b. 명시적으로 디폴트 생성자 사용하기.
Class SimpleClass{
Public:
SimpleClass() = delfalt; // 디폴트 생성자를 정의해라.
};

 

 


2) 생성자 오버로딩
SimpleClass(int n){ ... } // 매개변수가 1개일 경우, 오버로딩 가능.
SimpleClass(int n1, int n2){ ... } // 매개변수가 2개일 경우 오버로딩 가능.
SimpleClass(int n1 = 0, int n2 = 0){ ... } // 매개변수가 2개일 경우 오버로딩 가능. 그러나 매개변수가 1개여도, 0으로 디폴트 값 설정되었기 때문에 가능.

따라서, 위의 코드에서 주석처리를 해제하면,
SimpleClass sc2(100)의 경우, 두 경우가 실행할 가능성이 있으므로, 어떤 생성자를 생성할지 모호해짐.

 




 4. 이니셜라이저(:) 이용
- 생성자에서 이니셜라이저를 이용하면, 선언과 동시에 초기화가 이루어지는 형태로 바이너리 코드가 생성된다.

 

ex ) 이니셜라이저 사용 예시

 


 


 5. 소멸자
1) 소멸자란?
: 객체가 소멸될 때 자동으로 실행되는 클래스의 맴버함수.
: 클래스의 초기화를 돕도록 설계된 생성자와 반대로, 소멸자는 정리하는것을 돕는다.
* 클래스의 맴버 변수들이 단순하게, 기본 자료형이 값 형식이라면 크게 필요 없지만, 다른 리소스(ex. 동적 메모리, 파일 또는 데이터베이스 핸들러)라면 객체가 소멸되기 전에 어던 종류의 유지보수를 해야한다.


2) 소멸자의 규칙
1. 소멸자 이름은 클래스의 이름과 같아야 하며, 앞에 ~를 달아야 한다.
2. 소멸자는 인수가 없다.
3. 소멸자는 반환 값이 없다.
4. 소멸자는 클래스당 하나밖에 존재할 수 밖에 없다.


ex )

1. 생성자 부분 살펴보기
Person(const char * myname, int myage){ // 인자로 myname과, myage 입력
int len = strlen(myname) + 1; // 입력한 myname문자열 길이 + 1을, len에 넣는다.
name = new char[len]; // 힙공간에, char형의 len만큼의 배열 공간을 마련한다. 그리고 그 공간을 char형 포인터 변수 name이 가리킨다.
strcpy(name, myname); // myname을, name에 복사한다.
age = myage;
}

2. 소멸자 부분 살펴보기
~Person(){
delete [] name; // 생성자에서 할당한 힙에 있던 배열이 삭제된다.
cout<<"called destructor!"<<endl;
}

3. main부분 살펴보기
Person man1("Lee dong woo", 29); // man1이라는 새로운 Person 클래스의 객체를 인스턴스화한다. 이 과정에서 동적 할당이 발생한다.
...
return 0; // 이 시점에서 소멸자 실행. 이 코드에서는 생성자를 2번 실행해서, 힙에 두 개의 배열 공간이 존재하므로, 소멸자는 두 번 실행된다.

* 만약 명시적으로 객체를 삭제하게 된다면?
ex. delete man1; // 동적 할당을 진행한 man1을 삭제한다.
이 코드를 만나는 시점에서, 소멸자가 실행된다.

* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)

 

반응형