공부중

[C++] 생성자 호출순서 다시 돌아보기 본문

Programing/C, C++

[C++] 생성자 호출순서 다시 돌아보기

곤란 2024. 11. 27. 11:12
반응형

이 제목을 뭐로 지을까 하다가 일단 이렇게 지어놓았다.

이 글은 상속이란 무엇이고 다형성이란 무엇이다라는 설명이 아니고

단순히 생성자 호출순서에 대한 내 실수를 다시 되짚고자 작성하는 글이므로

상속에대한 개념, 그리고 다형성이라는 개념을 찾으려고 들어오신 분들은 뒤로가기를 추천드립니다.

 

문제가 되었던것은 어제 출력결과를 묻는 특정 문제를 보게 되었다.

코드는 아래와 같다.

#include <iostream>

class AA
{
public:
	AA() { std::cout << "A constructor" << std::endl; }
	~AA() { std::cout << "A destructor" << std::endl; }

};

class BB  : public AA
{
public:
	BB() { std::cout << "B constructor" << std::endl; }
	BB(int a) { std::cout << "B constructor int" << std::endl; }
	~BB() { std::cout << "B destructor" << std::endl; }

};

int main()
{
	BB bb(10);

	return 0;
}

AA의 자식으로 BB가 있고 main에 있는것처럼 생성 할 때 어떠한 출력 결과가 나올것인가.

 

이거 입사 시험에서 은근히 비슷한 유형의 문제를 많이 봐서 나는 그만 실수를 저지르고 말았다.

음.. 일단 virtual이 소멸자에 없네? 그러면 정답은 이거지 하고 너무 짧게 생각해버렸다.

A constructor
B constructor int
A destructor

이렇게 나올것이라고 생각하고 집에와서 복기를 해보니 하.. 자세히 안본 멍청한 내 자신을 탓해야했다.

 

정답은 아래와 같다.

A constructor
B constructor int
B destructor
A destructor

BB의 형으로 bb의 객체를 생성했기에

BB의 부모인 AA의 생성자를 먼저 호출하고 그 다음 BB의 생성자를 호출하는데

param으로 int를 받고 있으므로 BB(int a) 생성자가 호출된다.

그리고 BB의 형으로 소멸자가 먼저 호출되고 그 다음 부모인 AA의 소멸자가 호출되어서 이런 출력결과가 나왔다.

 

아니 그러면 나는 도데체 어떤 코드랑 햇깔린것인가?

int main()
{
	AA* bb = new BB(10);
	delete bb;

	return 0;
}

이 경우에는 AA의 형으로 BB의 객체를 담고있는 다형성을 보여주고 있다.

정말 간단하게 다형성이란, 기본 클래스(동물) 포인터로 파생 클래스(개,고양이, 기타 등등..) 객체를 관리하는것 이다.

이 경우에는 소멸자가 virtual이 아니면 내가 오답으로 적었던 아래의 출력 문구가 나오게 된다.

A constructor
B constructor int
A destructor

실제로 BB의 객체이지만 AA클래스 포인터를 기준으로 소멸자 호출을 하게 되는데 소멸자에 virtual이 붙어있지 않으므로 이 경우 자식이 있는지 알지 못하게 된다. 그러므로 소멸자 호출이 AA만 호출되게 된다.

그렇다면 main코드를 아래와 같이 바꾸면 어떻게 될것인가?

int main()
{
	BB* bb = new BB(10);
	delete bb;

	return 0;
}

이 경우 포인터의 형과 생성하는 객체의 형이 서로 같으므로 다형성을 보여주지 않고 있으므로

BB의 소멸자는 AA의 소멸자도 호출하기 때문에 위에서 봤던 BB bb(10); 으로 생성하고 제거한것과 같은 출력결과를 보여준다.

A constructor
B constructor int
B destructor
A destructor

 

다음에는 좀 꼼꼼히 봐야할것 같다 -_-..

 

 

반응형