I'm FanJae.

[C++] Constructor / Destructor 본문

C++/Basic

[C++] Constructor / Destructor

FanJae 2024. 8. 13. 16:39

※ 본 포스트는 코드누리 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
Comments