일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- operator overloading
- return by reference
- virtual function
- virtual destructor
- std::vector
- suffix return type
- std::ostream
- this call
- dynamic_cast
- pointer to member data
- std::cout
- base from member
- discord bot
- diamond inheritance
- virtual function table
- constructor
- member function pointer
- virtual inheritance
- c++ multi chatting room
- vector capacity
- placement new
- increment operator
- C++
- vector size
- conversion constructor
- c++ basic practice
- std::endl
- delete function
- 더 지니어스 양면포커
- new&delete
- Today
- Total
I'm FanJae.
[C++] Constructor / Destructor 본문
※ 본 포스트는 코드누리 C++ Basic 강의 내용을 보고 정리한 포스트입니다.
1. 생성자가 필요한 이유
#include <iosteram>
#include <string>
class Person
{
public:
std::string name;
int age;
};
int main()
{
Person p = {"kim",25};
}
- struct와 class는 사용 방법이 유사하여, 위와 같이 사용은 가능하다.
- 하지만 지난 시간 OOP 포스트에서 다뤘듯, 멤버 데이터를 외부에서 접근 시키는 행위는 다소 위험하다.
① 단계 1. 멤버 데이터를 private으로 수정한다.
class Peson
{
private:
std::string name;
int age;
};
- 따라서, 보통 멤버 데이터는 private으로 설정한다. 문제는 이렇게 하면, 구조체 초기화 문법 사용할 수 없다.
- 이런 경우, 멤버를 초기화 하는 멤버 함수를 제공해야 한다.
② 단계 2. 초기화를 하는 멤버 함수의 제공
class Peson
{
private:
std::string name;
int age;
public:
void init()
{
name = "kim";
age = 20;
}
};
- 초기화 하는 멤버 함수를 제공하여, 초기화를 할 수 있도록 처리해 주었다.
※ 다만, 이렇게 하면 모든 사용자가 객체를 생성하고 반드시 init()을 호출하도록 해야한다. 매우 번거롭다.
※ 정리하면, 객체 생성시 초기화 함수를 자동으로 호출되게 시켜 줄 수 있도록 해야 한다.
2. 생성자(Constructor)와 소멸자(Destructor)
class Peson
{
private:
std::string name;
int age;
public:
Person()
{
name = "kim";
age = 20;
std::cout << "Constructor" << std::endl;
}
~Person()
{
std::cout << "Destructor" << std::endl;
}
};
- 생성자는 클래스이름() 형태로 함수를 만들어 주면, 객체를 생성할 때 자동으로 호출되는 함수이다.
- 소멸자는 ~클래스이름() 형태로 모양의 함수를 만들어 주면, 객체가 파괴될 때 자동으로 호출되는 함수이다.
2-1. 생성자(Constructor)의 특징
class Point
{
int x;
int y;
public:
Point() { x = 0; y = 0; }
Point(int a, int b) { x = a; y = b; }
};
int main()
{
Point p1;
Point p2(1,2);
}
- 클래스 이름과 동일한 이름의 함수이다.
- 반환 타입을 표기하지 않고, 값 반환 할 수 없다.
- 인자가 없어도 되고 있어도 된다. 2개 이상 만드는 것도 가능하다. 즉 함수 오버로딩(Function Overloading)도 가능하다.
- 객체를 생성하면 생성자가 자동으로 호출되며, 생성자가 있어야 객체 생성이 가능하다.
2-2. 디폴트 생성자(Default Constructor)
class Point
{
int x;
int y;
public:
// Point() { x = 0; y = 0 }
};
int main()
{
Point p1;
}
- 인자가 없는 생성자
- 사용자가 생성자를 한 개도 만들지 않으면 컴파일러가 디폴트 생성자를 제공한다.
2-3. 생성자가 호출되는 다양한 경우
#include <iostream>
class Point
{
int x;
int y;
public:
Point() { x = 0; y = 0; std::cout << "ctor1" << std::endl;}
Point(int a, int b) { x = a; y = b; std::cout << "ctor2" << std::endl;}
};
int main()
{
Point p1; // 1번
Point p2(1,2); // 2번
Point p3{1,2}; // 2번, C++ 11
Point p4 = {1,2};// 2번, C++ 11
Point arr1[5]; // 1번, 5회
Point arr2[5] = { {1,2}, {1,1} }; // 2번 2회, 1번 3회
Point* p; // 객체 생성 아님. 생성자 호출 안됨.
p = static_cast <Point*> (malloc(sizeof(Point))); // 생성자 호출 안됨
free(p);
p = new Point; // 1번
delete p;
p = new Point(1,2); // 2번
delete p;
}
Point p1;
Point p2(1,2);
Point p3{1,2};
Point p4 = {1,2};
- p1의 경우는 Point Class에 동일한 함수 인자를 가진 생성자가 존재하여 1번 생성자를 호출한다.
- p2도 2번 생성자와 동일하므로 2번 생성자를 호출한다.
- p3, p4는 Uniform initialization으로, C++ 11부터는 가능한 문법이다. 이들은 모두 2번 생성자를 호출한다.
Point arr1[5]; // 1번, 5회
Point arr2[5]; = { {1,2}, {1,1}; // 2번 2회, 1번 3회
- arr1의 경우는 Point 객체를 5개 가지고 있는 배열이다. 따라서 이는 5번의 1번 생성자를 호출한다.
- arr2의 경우는 Point 객체를 5개 가지고 있는데, 이 중 2개는 초기화를 진행하고 있기에 2개는 2번 생성자를 호출하고, 3개는 1번 호출할 것이다.
p = static_cast<Point *>(malloc(sizeof(Point)));
- malloc은 지정된 크기만큼의 메모리를 할당하고, 메모리 블록의 시작 주소를 반환한다.
- 즉, 메모리 블록만 확보하는 작업이지 객체의 생성자 호출 등의 작업은 할 수가 없다.
※ 따라서 malloc은 생성자를 호출하지 않는다.
2-4. 생성자(Constructor)의 호출 순서
#include <iostream>
class Point
{
int x;
int y;
public:
Point() { x = 0; y = 0; std::cout << "Point()" << std::endl;}
Point(int a, int b) { x = a; y = b; std::cout << "Point(int, int)" << std::endl;}
};
class Rect
{
Point ptFrom;
Point ptTo;
public:
Rect() { std::cout << "Rect()" << std::endl; }
};
int main()
{
Rect rc;
}
- Rect Class에는 ptFrom과 ptTo 객체를 가지고 있다.
- Rect 라는 객체를 만들려고 확인을 해보니 다음과 같은 것이다.
- Rect를 구성하는 ptFrom과 ptTo도 객체이다. 따라서, 이들의 의미를 먼저 알아야만 Rect를 만들 수 있는 것이다.
- 즉, ptFrom과 ptTo가 먼저 만들어져야 Rect가 만들어지는 것이다.
Rect |
ptFrom |
ptTo |
- 정리하면, Rect 객체를 생성하면서 Rect의 멤버 데이터인 ptFrom과 ptTo도 생성된다.
- 이후, ptFrom의 생성자가 호출된다. 그 다음 ptTo 생성자가 호출된다.
- 마지막으로, Rect의 생성자가 호출되는 것이다.
※ 짧게 정리하면, 멤버의 생성자가 먼저 실행되고, 객체 자신의 생성자가 호출된다.
'C++ > Basic' 카테고리의 다른 글
[C++] Member initializer list, Default member initializer (0) | 2024.08.14 |
---|---|
[C++] Vector I (0) | 2024.08.13 |
[C++] OOP(Object Oriented Programming) I (0) | 2024.08.12 |
[C++] Explicit casting (0) | 2024.08.11 |
[C++] nullptr (0) | 2024.08.11 |