5.1 생성자와 소멸자
객체의 생성 및 소멸
객체의 생성
객체가 생성될 때 생성자가 자동으로 호출된다.
객체의 소멸
객체가 소멸될 때 소멸자가 자동으로 호출된다.
생성자와 소멸자
생성자와 소멸자는 자동으로 호출되는 함수이다.
- 생성자: 객체가 생성되는 시점에서 자동으로 호출되는 멤버 함수
- 솜려자: 객체가 소멸되는 시점에서 자동으로 호출되는 멤버 함수
생성자와 소멸자 함수의 사용
- 생성자: 객체가 생성될 때 객체가 필요한 초기화를 위해
- 소멸자: 객체가 소멸될 때 객체의 정리를 위해
생성자와 소멸자 이름
- 생성자: "클래스이름()" 형식의 함수 참고) 생성자는 매개변수 받을 수 있음
- 소멸자:"~클래스이름()" 형식의 함수
생성자와 소멸자는 리턴 값이 없음
- 리턴 타입 없음. void도 안됨
생성자 특징
객체 생성 시 오직 한 번만 호출
- 자동으로 호출됨. 임의로 호출할 수 없음. 각 객체마다 생성자 실행
생성자는 중복 가능
- 생성자는 한 클래스 내에 여러 개 가능
- 중복된 생성자 중 하나만 실행
string 클래스의 생성자 중복 사례
class string{
...
public:
string(); // 빈 문자열을 가진 스트링 객체 생성
string(string& str); // str을 복사한 새로운 스트링 객체 생성
string(char* s); // '\0'로 끝나는 C-스트링 s를 스트링 객체로 생성
...
};
string str; // 빈 문자열
string address("너네집");
string copyAddress(address); // address의 문자열을 복사한 별도의 copyAddress 생성
객체 생성 및 생성자 실행 과정
디폴트 생성자
1. 생성자는 꼭 있어야 하는가?
- 있어야 한다. C++ 컴파일러는 객체가 생성될 때, 생성자 반드시 호출
2. 개발자가 클래스에 생성자를 작성해 놓지 않으면?
- 컴파일러에 의해 기본 생성자가 자동으로 생성
디폴트 생성자란?
- 매개변수 없는 생성자. 기본 생성자라고도 부름.
- 객체를 생성할 때 별도로 지정하지 않으면 항상 디폴트 생성자로 초기화 됨
class Circle{
...
Circle(); // 기본 생성자, 컴파일러가 자동 생성
};
디폴트 생성자가 자동으로 생성되는 경우
생성자가 하나도 작성되어 있지 않은 클래스의 경우
- 컴파일러가 디폴트 생성자 자동 생성
디폴트 생성자가 자동으로 생성되지 않는 경우
생성자가 하나라도 선언된 클래스의 경우
- 컴파일러는 디폴트 생성자를 자동 생성하지 않음
디폴트 인자를 사용한 함수 중복 간소화
디폴트 인자의 장점 - 함수 중복 간소화
중복 함수들과 디폴트 매개변수를 가진 함수를 함께 사용 불가
소멸자
소멸자
- 객체가 소멸되는 시점에서 자동으로 호출되는 함수
- 오직 한번만 자동 호출, 임의로 호출할 수 없음
- 객체 메모리 소멸 직전 호출됨
- "~클래스이름()" 형식의 함수
- 인자를 가질 수 없기 때문에 오버로딩할 수 없음
소멸자 특징
소멸자의 사용
- 객체가 사라질 때 마무리 작업을 위함
- 실행 도중 동적으로 할당 받은 메모리 해제, 파일 저장 및 닫기, 네트워크 닫기 등
소멸자는 리턴 타입이 없고, 어떤 값도 리턴하면 안됨
- 리턴 타입 선언 불가
중복 불가능
- 소멸자는 한 클래스 내에 오직 한 개만 작성 가능
- 소멸자는 매개변수 없는 함수
소멸자가 선언되어 있지 않으면 디폴트(기본) 소멸자가 자동 생성
- 컴파일러에 의해 디폴트 소멸자 코드 생성
- 컴파일러가 생성한 디폴트 소멸자: 아무 것도 하지 않고 단순 리턴
Circle 클래스에 솜려자 작성 및 실행
생성자/소멸자 실행 순서
객체가 선언된 위치에 따른 분류
지역 객체
- 함수 내에 선언된 객체로서, 함수가 종료하면 소멸된다.
전역 객체
- 함수의 바깥에 선언된 객체로서, 프로그램이 종료할 때 소멸된다.
객체 생성 순서
- 전역 객체는 프로그램에 선언된 순서로 생성
- 지역 객체는 함수가 호출되는 순간에 순서대로 생성
객체 소멸 순서
- 함수가 종료하면, 지역 객체가 생성된 순서의 역순으로 소멸
- 프로그램이 종료하면, 전역 객체가 생성된 순서의 역순으로 소멸
new를 이용하여 동적으로 생성된 객체의 경우
- new를 실행하는 순간 객체 생성
- delete 연산자를 실행할 때 객체 소멸
int* a = new int;
delete a;
int* b = new int[10];
delete[] b;
기본적으로 생성 순서의 역순으로 소멸자가 호출되지만, delete로 해제하면 그때 바로 해제된다.
지역 객체와 전역 객체의 생성 및 소멸 순서
객체 간의 초기화와 대입
같은 클래스의 객체 간에 서로 초기화나 대입이 가능
객체 간의 초기화: 복사 생성자 이용
(본인 클래스와 같은 타입의 참조를 매개변수로 받음)
- 같은 클래스의 다른 객체와 같은 값을 갖도록 초기화
- 클래스의 멤버 변수를 1대1로 초기화
객체 간의 대입: 대입 연산자 이용
(컴파일러가 자동 생성해준다. 같은 타입은 메모리 구조가 같기 때문(단, 얕은 복사), 깊은 복사 하려면 연산자 오버로딩)
- 같은 클래스의 다른 객체의 값을 대입
- 클래스의 멤버 변수를 1대 1로 대입
Stack s1(5);
Stack s2 = s1; // 객체 간의 초기화 = 복사 생성자
Stack s3;
s3 = s1; // 객체 간의 대입, 대입 연산자
디폴트 함수들
개발자가 따로 정의하지 않으면 컴파일러에 의해서 제공되는 함수
- 디폴트 생성자
- 디폴트 소멸자
- 디폴트 복사 생성자
- 디폴트 대입 연산자
5.2 분할 컴파일
바람직한 C++ 프로그램 작성법
클래스를 헤더 파일과 cpp 파일로 분리하여 작성
- 클래스마다 분리 저장
- 클래스 선언 부: 헤더 파일(.h)에 저장
- "클래스 이름.h"
- 클래스 구현 부: cpp 파일에 저장(멤버함수의 구현)
- 클래스가 선언된 헤더 파일 include
- "클래스 이름.cpp"
- 클래스가 선언된 헤더 파일 include
- main() 등 전역 함수나 변수는 다른 cpp 파일에 분산 저장
- 필요하면 클래스가 선언된 헤더 파일 include
목적
- 클래스 재사용
분할 컴파일
명령어)
g++ -o main.cpp Circle.cpp
./main.exe
헤더 파일의 중복 include 문제
헤더 파일을 중복 include 할 때 생기는 문제
결과적으로 이렇게 되는데 아래 예시처럼 된다는 것이다.
헤더 파일의 중복 include 문제를 조건 컴파일로 해결
헤더의 중복 포함을 막는 방법
- 규칙1. 헤더 파일의 이름을 따서 심볼을 만든다 (예: TEST_H)
- 규칙2. 헤더 파일의 제일 앞에 이 심볼을 사용해서 #ifndef, #define 명령을 추가한다.
- 규칙3. 헤더 파일의 제일 끝에 #endif를 추가한다.
- 참고) #pragma once 도 있지만 지원 안하는 컴파일러도 있음
'CIRCLE_H를 define 하지 않았다면, #endif 가 나오기 전까지를 포함시켜라.' 라는 것이다.
'공부 > C++' 카테고리의 다른 글
7. 여러가지 객체의 생성방법 (0) | 2024.05.14 |
---|---|
6. 접근지정자, const 객체, static 멤버 (1) | 2024.04.18 |
4. 클래스와 객체의 기본 (0) | 2024.04.09 |
3. 개선된 함수 기능 (0) | 2024.03.31 |
2. 포인터와 레퍼런스 (1) | 2024.03.30 |