자... 한번
생성자부터 소멸자까지 한번 쓸어담아봅시다!
물론 예제를 통해서 말입니다 하하...
우선, header입니다.
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 | #pragma once #include <string> using namespace std; class Stu { int num; string name; int hp; public: // 기본 생성자 //Stu(); // 생성자 Stu(int num); Stu(int num, string name); // 복사 생성자 Stu(const Stu &stu); // 기본 소멸자 //~Stu(); void Study(); int GetHp(); int GetNum(); }; | cs |
우선 생성자에 대해서 설명을 드리자면
우선 클래스의 이름과 같습니다. 하지만 리턴형이 없죠...
반환 형식을 명시할 수 없습니다... 해당 형식은 포인터로 받는 것이 명확합니다...
아무튼... 생성자는 '객체가 메모리에 생성될 때 해야할 일들을 정의' 하는 일을 담당합니다.
그렇다면 반대로 생각해봅시다. 생성이 있다면 소멸이 있겠죠...
그래서, 소멸자는 '객체가 메모리에 해제 될 때 해야할 일들의 정의'하는 일을 담당합니다.
생성자나 소멸자나 지금 그게 우리에게 불편한 생성자는 아닙니다...
바로 저기... 복사 생성자가 불편하죠...
복사생성자는 무엇일까요?
그 전에 알아봐야할 것이 있습니다. 바로 레퍼런스 변수입니다.
1 2 3 4 5 6 7 8 9 10 | int n = 5; //레퍼런스 변수 int * pn; //&은 레퍼런스 연산자 int &r = n; //&은 주소 연산자 pn = &n; | cs |
레퍼런스는 C에서 언급한 적이 있는데, 바로 참조를 뜻합니다.
기본적으로 &은 주소를 나타낼 때 쓰는 연산자라고 알고 있었는데요,
C만 하시던 분들이라면 int &r = n; 과 같은 부분은 상당히 어색해 보일 수 있습니다.
이 레퍼런스 변수는 반드시 초기화할 때에만 사용을 할 수 있으며,
r과 n은 같은 메모리의 이름이라는 것으로 이해하시면 됩니다.
아무튼... 복사 생정자에 대해서 말을 하고 있었죠...
복사한다 아시죠? 그 말인 즉, 위의 예시를 보시면 아시겠지만 다른 객체를 인자로
전달 받아 복사된 객체를 생성하는 것이죠...
참고로 생성자, 소멸자와 같이 없으면 디폴트로 복사 생성자를 만들어줍니다..
자... 그럼 이어서 진행해보도록 하겠습니다.
헤더에 명시되어있는 함수들의 집합소로 이동해보시죠...
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include "Stu.h" #include <iostream> using namespace std; Stu::Stu(int num) { this->num = num; name = ""; hp = 0; cout << "인자 하나 받은 생성자닷" << endl; } Stu::Stu(int num, string name) { this->num = num; name = name; hp = 0; cout << "인자 두개 받은 생성자닷" << endl; } Stu::Stu(const Stu &stu) { this->num = stu.num + 100; this->name = stu.name; this->hp = stu.hp; cout << "난 복사생성자지롱" << endl; } Stu::~Stu() { cout << "나는 소멸자인데 말입니다.." << endl; } void Stu::Study() { cout << num << "번 학생~" << endl; hp++; } int Stu::GetHp() { return hp; } int Stu::GetNum() { return hp; } | cs |
많은 분들이 처음 C++에서 코딩을 하시며 놀아나실 때에...
어느 클래스에 약속된 함수인지 '클래스 :: ' 하는 것을 많이들 잊어드신다고 해요...
물론 저도,.. 푸하하 까먹지 맙시다!
아무튼,
매개변수가 중복적으로 정의 되어있습니다.
하지만 매개변수가 다르다는 점~
결국 데이터를 몇개 받아오느냐의 차이이지 하는일은 같다는 점...
그리고 저기 보이네요... 복사생성자...
복사해온다고 햇죠? Call By Value 생각나시는지... 값에 의한 복사 말입니다.
값을 통째로 덤핑한다고 하죠...
객체 자체를 전달해야되기 때문에 레퍼런스 변수를 사용해야합니다.
또한 복사의 개념이 있다보니, 원본이 변경된다면 복사의 의미가 없어지잖아요?
그래서 const와 같은 키워드를 통해 변경하지 못하도록 해야합니다...
조금있다가 다시 보도록 하고 이제 main 함수를 살펴보도록 하죠...
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 | #include <iostream> #include "Stu.h" using namespace std; Stu Foo(Stu s); void main() { cout << "하나" << endl; Stu s(3); cout << "두울" << endl; //다른 객체를 인자로 Stu s2(s); // Stu s2 = s; cout << "세엣" << endl; cout << "s: " << s.GetHp() << endl; s2 = Foo(s); cout << "네엣" << endl; cout << "s: " << s.GetHp() << "번호:" << s.GetNum() << endl; cout << "s2: " << s2.GetHp() << "번호:" << s2.GetNum() << endl; } Stu Foo(Stu s) { cout << "Foo 시작" << endl; s.Study(); cout << "s: " << s.GetHp() << endl; return s; } | cs |
자.. 지금까지 저는 말입니다 변수 초기화는
' int n = 3; ' 이런식으로 해야되는 줄만 알았는데요, C++ 스타일의 초기화를 아십니까?
1 2 | int n = 3; int n(3); | cs |
이렇게 초기화를 할 수 있습니다.... 그러면 복사 생성자에 대해서 조금 더 쉽게 다가갈 수 있겠네요...
Stu s2(s); 를 Stu s2 = s; 와 같다고 생각한다면
값을 복사하는거 맞네요! 왜냐하면 s의 값을 s2에 넣는 것이니까요!
즉, "Stu형 s2라는 객체가 생성 된 다음 s를 인자로 받을 수 있는 생성자 호출해서
생성 완료하겠다!" 이겁니다....
복사 생성자도 마찬가지로 복사 생성자가 정의되어있지 않다면 디폴트 복사 생성자가 생겨나는 것은
아까 말씀 드렸고요.... 그런데 우리가 보는 코드에는 복사 생성자가 있습니다.
자 정리해보져... 전체적으로 코드가 돌아가는 순서에 대해서 서술해보도록 하겠습니다.
우선 '하나' 라는 문자가 출력 되고나서,
Stu 형식의 s라는 객체가 생성됩니다. 물론, 3이라는 값이 매개변수로 들어가
값이 3으로 초기화 되겠군요...
다음으로 '둘'이라는 문자가 출력되고
다른 객체를 인자로 받는 객체를 생성하려고 하네요...
이때 복사 생성자가 나타납니다... 값이 싸그리 dumping 되어서 복사가 되겠군요...
그리구 쭉 쭉 내려가다가 's2 = Foo(s); 를 주목해주시길 바랍니다.
Foo라는 함수에 객체 s를 인자로 보내버리네요...
이때 주목해야할 점은 이 코드는 call by value를 기반으로 구현이 되었기 때문에
값이 복사되어 Foo 함수의 s라는 지역변수에 복사가 된다는 것을 반드시 아셔야 됩니다.
그렇다면 s라는 지역변수에 main 함수의 s인자를 받으니
복사 생성자가 또한번 나타나게 됩니다...
그리구 쭉쭉 내려가다가 말입니다...
return을 만나게 되면 Foo라는 함수에서 지지고 볶고 하며 나온 s라는 객체를 반환하게 됩니다.
이때 main으로 돌아오면서 값을 임시로 저장해둘 메모리 공간이 할당됩니다.
자... 그럼 s는 객체입니다... 그걸 받을 만한 임시의 메모리 공간이 생기고
값을 복사받아야하니 또 복사 생성자가 나타나게 되죠...
그 값을 인수인계 해준 Foo 함수의 매개 변수는 임무를 마치고 소멸하게 됩니다...
다음으로 임시 객체는 s2에 값을 대입해주고 또 소멸하게 되버리죠...
그리고 쭉쭉 내려가며 끝에 다달았을때
생성되어있던 객체들이 소멸되는 것으로 프로그램이 종료되겠습니다...
어렵죠?...
날 잡고 복사 생성자에 대해서 포스팅할 기회가 있으면 좋겠네요 ....
C++ 마스터가 되고싶당....
'삽질의 현장 > - C++' 카테고리의 다른 글
#007_시(c)시(c)해서 C++?!_상속을 가지고 놀아보자~ (0) | 2015.07.08 |
---|---|
#006_시(c)시(c)해서 C++?!_클래스간의 관계 (0) | 2015.07.06 |
#004_시(c)시(c)해서 C++?!... C와 C++의 변수와 동적할당 (0) | 2015.07.02 |
#003_시(c)시(c)해서 C++?!... C와 C++의 캡슐화차이 (0) | 2015.07.02 |
#002_시(c)시(c)해서 C++?!... C와 C++의 차이 실제 예시 (0) | 2015.07.02 |