11) 클래스(2)
11-1. 생성자
파이썬의 __init__()
함수는 인스턴스가 생성된 이후에 멤버변수들의 초기화를 위해서 단 한번만 호출되는 메서드입니다.
소위 생성자라고 불리는데, C++에서도 이러한 개념이 있습니다.
자바와 비슷하게 C++에서는,
- 생성자의 이름은 클래스 이름과 같습니다. (ex,
Book
클래스의 생성자는Book()
) - 반환값이 없음에도 void타입을 명시하지 않습니다.
- 반드시 public 영역에서 선언되어야 합니다.
11-2. 생성자의 선언, 호출
생성자의 원형과, 선언 방식은 일반적인 멤버함수와 비슷합니다.
class Book {
private:
int id_; // 이런식으로 _를 붙여서 명명하는것을 권장하는듯합니다.
int price_;
public:
Book(int, int); // 원형
};
Book::Book(int id, int price){
id_ = id;
price_ = price;
} // 선언
하지만, 생성자의 호출은 다양한 방법이 있습니다.
int main(){
Book my_book(1234, 10000);
// Book my_book = Book(1234, 10000);
// Book my_book = {1234, 10000};
}
주석을 친 두 가지 방법 모두 가능한 방법인데,
마지막 방법은 매우 신기합니다. 배열 표기법을 객체에 대입한다는게 사실 잘 와닿지는 않지만 아무튼 된다고 합니다.
11-3. 디폴트 생성자
저번 포스트에서는 생성자에 대한 언급도 안하고 객체를 생성할 수 있었습니다.
왜냐하면 디폴트 생성자가 멤버변수를 초기화해주기 때문입니다.
Default constructor
-
매개변수를 가지지 않음.
-
그렇지만 멤버변수들을 기본값(0, NULL, 빈 문자열, …)등으로 초기화시켜줌.
-
생성자를 단 하나도 정의하지 않을 때에만 존재함.
(컴파일러가 자동으로 만들어줍니다.)
class Book {
private:
int id_, price_;
public:
void print();
};
void Book::print(){
std::cout << id_ << " " << price_;
}
int main(){
Book my_book;
// Book my_book() 은 에러를 발생시킵니다.
my_book.print();
}
// 출력값, 전부 0으로 초기화된 모습입니다.
0 0
하지만, 우리가 생성자를 정의함으로 인해 디폴트 생성자가 없어진다고 해서 크게 걱정하실 필요는 없습니다.
왜냐하면 생성자 오버로딩을 통해서 비슷한 기능을 구현하게 만들 수 있기 때문입니다.
11-4. 복사 생성자
파이썬에는 copy 라이브러리의 deepcopy 함수를 통해서 객체의 깊은 복사를 할 수 있습니다.
이와 비슷하게, C++에서는 복사 생성자를 통해서 다른 객체와 동일한 값들을 가지지만, 주소는 다른 객체를 생성할 수 있습니다.
class Book {
private:
int id_, price_;
public:
void print();
Book(Book &Book);
Book(int, int);
};
void Book::print(){
std::cout << "id : " << id_ << " price : " << price_ << std::endl;
std::cout << "객체의 주소 :" << this<< std::endl;
}
Book::Book(Book &Book){
id_ = Book.id_;
price_ = Book.price_;
// 신기하게도 private인데 불구하고 접근이 가능함!
} // 복사 생성자
Book::Book(int id, int price){
id_ = id;
price_ = price;
} // 원래 생성자
int main(){
Book my_book(1234, 10000);
my_book.print();
Book your_book(my_book);
your_book.print();
}
// 출력값
id : 1234 price : 10000
객체의 주소 :0x7ffe36aa3948
id : 1234 price : 10000
객체의 주소 :0x7ffe36aa3940
11-5. 부록) Copy constructor에서 private 변수에 접근가능한 이유
참고링크 : https://stackoverflow.com/questions/4117002/why-can-i-access-private-variables-in-the-copy-constructor
Book::Book(Book &Book){
id_ = Book.id_;
price_ = Book.price_;
// 신기하게도 private인데 불구하고 접근이 가능함!
}
왜냐하면 access modifier는 object level이 아니라 class level에서 작동하기 때문입니다.
그래서 같은 클래스에 있는 두 object는 서로의 데이터에 접근할 수 있습니다.
-
효율성 때문에 이런 개념이 생겨났습니다.
만약 객체단위로 access modifier가 적용되어있다면,
this == other
를 비교하기 위해서 엄청나게 많은 연산을 해야하기 때문입니다.
11-5. 소멸자
파이썬에서는 __del__
이라는 매직메서드가 있듯이, C++에도 소멸자라는 비슷한 개념이 있습니다.
소멸자는 객체가 메모리상에서 사라질 때에 발생하는 함수인데요,
- 객체가 메모리상에서 사라지는 경우들
- 정적 변수(startic, extern) : 프로세스의 data 영역에 저장되며, 프로그램이 종료될 때 사라짐.
- 이 때는, 컴파일러가 소멸자를 호출합니다.
- 자동 변수(지역 변수) : 프로세스의 stack 영역에 저장되며, 해당 블록 호출이 끝난 후 사라짐.
- 동적할당된 포인터 : new 연산자를 통해서 프로세스의 heap 영역에 저장되며, delete 연산자를 사용한 뒤에 제거됨.
- 소멸자의 특징
- 인수를 가지지 않음.
- 반환값이 없으나, void 형으로 선언하지 않음.
- 문법 :
~
을 붙여서 사용
~Book();