멤버 변수의 초기화
- 객체를 생성하면 메모리에 즉시 생성되지만, 모든 멤버 변수를 초기화하기 전까지 사용할 수 없음
- 일반적인 초기화 방식으로 초기화할 수 없음 (private 멤버에는 직접 접근할 수 없기 때문)
-> private 멤버에 접근할 수 있는, 초기화만을 위한 public 함수가 필요!
생성자 (constructor)
- 객체의 생성과 동시에 멤버 변수를 초기화해주는 멤버 함수
- 클래스 생성자의 이름은 해당 클래스의 이름과 같음
생성자 특징
- 초기화를 위한 데이터를 인수로 전달받을 수 있음
- 반환값이 없지만, void형으로 선언하지는 않음
- 객체를 초기화하는 방법이 여러 개 존재할 경우, overloading 규칙에 따라 여러 개의 생성자를 가질 수 있음
생성자 선언
생성자 원형 예)
Book(const string& title, int total_page);
생성자 선언 예)
Book::Book(const string& title, int total_page) {
title_ = title;
total_page_ = total_page;
set_percent();
...
}
생성자 호출
C++에선 클래스에서
- 객체를 생성할 때마다 해당 클래스의 생성자가 컴파일러에 의해 자동으로 호출됨
- 사용자가 직접 생성자를 명시적으로 호출할 수도 있음
객체 생성하면서 생성자가 암시적으로 호출되는 예)
int main() {
Book web_book("HTML과 CSS", 350); // 생성자의 암시적 호출
// 생성자가 호출되어 멤버 변수인 percent_가 초기화되었는지 확인
cout << web_book.percent_;
}
void Book::set_percent() {
percent_ = (double) current_page_ / total_page_ * 100;
}
디폴트 생성자
- 객체가 생성될 때 사용자가 초깃값을 명시하지 않으면, 컴파일러가 자동으로 제공하는 생성자
- 클래스에 생성자가 단 하나도 정의되지 않았을 때만! 컴파일러가 자동 제공 (아니면 초깃값 없이 객체를 선언하면 오류 발생)
- 인수를 전달받지 않으므로, 매개변수를 갖지 않음
- 대부분의 디폴트 생성자가 0이나 NULL, 빈 문자열 등으로 초기화 진행
디폴트 생성자의 정의 (사용자가 직접)
1. 함수 오버로딩을 이용
2. 디폴트 인수를 이용 : 기존 생성자의 모든 인수에 디폴트 인수를 명시
(클래스는 단 하나의 디폴트 생성자를 가질 수 있으므로, 둘 중 하나의 방법만 사용해야 함)
1) 함수 오버로딩 예
Book();
2) 디폴트 인수 예
Book::Book(const string& title = "웹 프로그래밍", int total_page = "100");
디폴트 생성자를 갖는 객체의 선언
1) Book web_book; // 디폴트 생성자의 암시적 호출
2) Book web_book = Book(); // 디폴트 생성자의 명시적 호출
3) Book *ptr_book = new Book; // 디폴트 생성자의 암시적 호출
오류) Book web_book(); // 컴파일러가 객체 선언이 아닌 함수의 호출로 보게 되므로 오류 발생
얕은 복사 (shallow copy)
- 값을 복사하지 않고, 값을 가리키는 포인터를 복사! (즉, 주소값을 복사한다는 의미)
- 복사하는 대상과 참조하고 있는 실제 값은 같음
- 대입 연산자( = )를 이용한 객체의 대입에서 수행됨
- 변수의 생성에서 얕은 복사는 문제되지 않지만, 객체의 생성에서는 문제가 발생할 수도 있음 (특히 객체가 메모리의 힙(heap) 영역을 참조할 경우)
깊은 복사 (deep copy)
- '실제 값'을 복사
- 복사 생성자를 재정의해서 원하는 멤버 변수만 복사해주는 방법을 사용
- 복사 생성자에서는 const로 인자를 받아서 기존 객체의 멤버 변수를 변경할 수 없도록 하기를 권장
복사 생성자 (copy constructor)
- 자신과 같은 클래스 타입의 다른 객체에 대한 참조(reference)를 인수로 전달받아, 그걸 이용해 자신을 초기화
- 새롭게 생성되는 객체가 원본 객체와 같으면서도, 완전한 독립성을 갖게 해줌
- 깊은 복사에 해당됨
복사 생성자를 사용하는 주요 상황
- 객체가 함수에 인수로 전달될 때
- 함수가 객체를 반환할 때
- 새로운 객체를 같은 클래스 타입의 기존 객체와 똑같이 초기화할 때
복사 생성자 선언 예)
Book::Book(const Book& origin) {
title_ = origin.title_;
total_page_ = origin.total_page_;
...
}
복사 생성자 활용 예)
Book web_book("HTML", 300);
Book html_book(web_book); // 복사 생성자를 이용해, 새롭게 생성되는 html_book 객체를 web_book 객체로 초기화
->컴파일러에 의해 다음과 가은 복사 생성자를 사용한 것으로 해석됨
-> Book html_book = Book(web_book);
소멸자 (destructor)
- 객체 수명이 끝나면, 생성자의 반대 역할을 수행하는 멤버 함수
- 객체 수명 끝나면 컴파일러가 자동으로 호출하여 사용이 끝난 객체를 정리해 줌 (그 외에는 수행할 작업이 없음)
- 클래스 소멸자의 이름은 해당 클래스의 이름과 같고, 이름 앞에 물결 표시(~)를 붙여 생성자와 구분함
소멸자의 특징
- 인수를 갖지 않음
- 반환값이 없지만, void형으로 선언하지 않음
- 클래스는 소멸자를 단 하나만 가질 수 있음 (생성자는 여러 개 가능)
- const, volatile, static으로 선언될 수 없지만, const, volatile, static으로 선언된 객체의 소멸을 위해서 호출은 가능
- 소멸자의 원형은 클래스 선언의 public에 포함되어야 함
소멸자 원형 예)
~Book();
소멸자 선언 예)
Book::~Book() {
// 프로그램 종료 시 컴파일러에 의해 자동으로 호출됨
cout << "Book 객체의 소멸자가 호출되었습니다.\n";
}
소멸자의 호출
C++에서 소멸자의 호출 시기는 컴파일러가 알아서 정함
- 메모리의 데이터 영역 : 해당 프로그램이 종료될 때
- 메모리의 스택 영역 : 해당 객체가 정의된 블록을 벗어날 때
- 메모리의 힙 영역 : delete를 사용하여 해당 객체의 메모리를 반환할 때
- 임시 객체 : 임시 객체의 사용을 마쳤을 때
참고)
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
'[공부] > C++' 카테고리의 다른 글
[C++] 기본 정리 16 - OOP의 캡슐화(프렌드, 정적 멤버, 상수 멤버) (0) | 2024.02.25 |
---|---|
[C++] 기본 정리 15 - 연산자 오버로딩 (1) | 2024.02.24 |
[C++] 기본 정리 13 - 클래스, 객체 지향 프로그래밍, this 포인터 (1) | 2024.02.24 |
[C++] 기본 정리 12 - C++ 범위(유효 범위, 연결, 네임스페이스) (0) | 2024.02.22 |
[C++] 기본 정리 11 - C++ 함수(인라인 함수) (0) | 2024.02.22 |