[생성자란?]

생성자란 객체를 즉시 사용할 수 있는 상태로 초기화 시켜주는 클래스의 멤버함수이다.

따라서 생성자를 사용하면 생성된 객체의 상태를 일일이 신경을 써 초기화 하지 않고도 사용 할 수 있다.

단, 생성자가 하는 일이 너무 많으면 오히려 코드에 대한 이해도가 복잡해 질수 있음으로 꼭 필요한 작업만 사용하는 것이 좋다.

 

- 클래스로 만들어지는 객체를 초기화 해주는 멤버함수이다.

- 클래스로 객체를 선언할 때 자동적으로 호출된다.

- 사용자가 직접 호출해 사용할 수 없다. (함수의 호출이 명시적이지 않다.)

- 이름은 클래스의 이름과 동일하게 작성해야 한다.

- 리턴 값이 void인 함수이여야 하며 void를 생략하여 함수를 선언하고 정의한다. (리턴 값을 가질 수 없음.)

- 객체 생성 때 마다 호출되어 생성된 객체의 멤버변수를 초기화 시킨다.

- 가상함수로 선언 될 수 없다.

 

생성자 함수의 선언 및 정의 방법

생성자 함수도 멤버 함수임으로 클래스 내에 정의 하면 된다.

또한 다른 멤버함수와 같이 클래스 내부에서는 함수의 선언만 하고 클래스 외부에서 정의하는 것도 가능하다.

1
2
3
4
5
6
7
8
9
//클래스 내부에 생성자 함수를 정의 하는 방법
class 클래스명{
    :
    public:
        클래스명() { //생성자 함수의 정의.  return type을 쓰지 않는다.
            :       //이곳에 생성자 함수의 내용을 기재 한다.
        }
        :           //클래스의 다른 내용
};
cs
1
2
3
4
5
6
7
8
9
10
11
//클래스 내부에는 생성자 함수에 대한 선언을 하고 클래스 외부에 생성자 함수를 정의 하는 방법
class 클래스명{
    :
    public:
        클래스명()   //생성자 함수의 정의.  return type을 쓰지 않는다.
        :           
};
 
클래스명::클래스명() {
    :                //이곳에 생성자 함수의 내용을 기재 한다.
}
cs

 

생성자 함수는 오버로딩이 가능하다.

생성자 함수를 오버로딩 한다면 객체를 선언 할 때 건네준 매개변수 값에 따라 어떠한 생성자 함수가 호출 될지 결정된다.

오버로딩 함수에는 수적 제한이 없으며 매개변수가 없는 생성자 함수를 dafault 생성자 함수라 한다.

1
2
3
4
5
6
7
8
9
/* 예제1 */
Point p1;          // default 생성자 함수가 호출된다.
Point p2(1020);  // 매개변수를 받아가는 생성자 함수가 호출된다.
 
/* 예제2 */
Stud arr[3= { Stud(), Stud(2,25), Stud(3,35) };
arr[0].prn();      // 번호: 0  나이: 0
arr[1].prn();      // 번호: 2  나이: 25
arr[2].prn();      // 번호: 3  나이: 35
cs

[소멸자란?]

소멸자란 객체의 사용이 끝난 후 객체에 대한 뒤처리 작업 등을 자동으로 수행 할 수 있도록 해주는 class의 멤버함수 이다.

소멸자를 사용하면 생성된 객체에 대한 뒤처리를 신경쓰지 않고 편하게 프로그래밍을 할 수 있다.

단, 생성자와 마찬가지로 소멸자 함수가 하는 작업이 너무 많아지면 프로그램의 이해가 어려워지고 오류 발생 위험이 높아지는 등의 문제가 있음으로

꼭 필요한 내용만 소멸자 함수에 포함시키는게 좋다.

 

- 클래스로 만들어지는 객체에 대한 뒤처리를 해주는 멤버함수이다. (뒤처리 작업 = 동적메모리할당 해제)

- 사용중인 객체가 소멸되는 시점에 자동으로 호출된다.

- 직접 호출해 사용할 수 없다.

- 클래스의 이름과 동일하게 작성해야 하되, 생성자 함수와 구분하기 위해 함수명 앞쪽에 ~연산자를 붙인다. (~는 틸드(tilde) 또는 bit not으로 읽으면 된다.)

- 리턴 값이 void인 함수여야 하며 void를 생략하여 함수를 선언하고 정의 한다. (리턴 값을 가질 수 없다.)

- 매개변수를 받아올 수 없다. 따라서 소멸자에 대한 오버로딩이 불가함으로 class 하나에 오직 한 개의 소멸자 함수만 존재해야 한다.

- 객체가 소멸될 때 마다 호출되어 소멸된 객체에 대한 뒤처리 작업을 한다. (전역객체는 프로그램 종료 시 한번, 지역객체는 객체 소멸 시마다 실행된다.)

 

소멸자 함수의 사용방법

소멸자 함수는 객체에 대한 뒤처리를 하기 위해 사용하며 주로 동적 메모리 할당을 자동으로 해제하기 위해 사용한다.

1
2
3
4
5
6
7
8
9
10
//클래스 내부에 소멸자 함수를 정의 하는 방법
class 클래스명{
    :
    public:
        :
        ~클래스명(){ //소멸자 함수의 정의.  return type을 쓰지 않는다.
            :       //이곳에 소멸자 함수의 내용을 기재 한다.
        }
        :           //클래스의 다른 내용
};
cs

[복사생성자란?]

복사생성자란 객체를 만들면서 생성자 함수에 매개변수로 기존에 생성한 객체를 건네줄 경우 컴파일러가 자동으로 생성해주는 생성자 함수이다. 원래 생성자 함수에 어떠한 매개변수를 건네주려면 해당 매개변수를 받아올 수 있는 생성자 함수를 사용자가 직접 만들어야 하지만 객체가 매개변수로 넘어갈 경우에는 사용자가 생성자 함수를 만들지 않아도 컴파일러가 자동으로 복사생성자를 만들어 객체를 매개변수로 받아올 수 있게 해준다.

 

- 컴파일러에 의해 자동으로 생성되는 생성자 함수이다.

- 복사생성자는 객체를 생성자의 매개변수로 받아갈 수 있게 해준다.

- 필요할 경우 사용자가 직접 복사 생성자를 만들어 사용 할 수도 있다.

 

 

복사생성자의 사용방법

사용자가 직접 정의하지 않아도 생성자 함수에 매개변수로 객체를 건네주면 컴파일러가 자동으로 생성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream.h>
 
class Stud {
    private :
        int no;
        int nai;
    public :
        Stud(int x, int y) {
            no = x, nai = y;
        }
        void print() {
            cout << "번호: "<< no << "\t" << "나이: " << nai << endl;
        }
};
 
void main() {
    Stud arr[3= { Stud(115), Stud(225), Stud( arr[1] ) };
    arr[0].print();
    arr[1].print();
    arr[2].print();
}
cs
//실행결과
번호: 1          나이: 15
번호: 2          나이: 25
번호: 2          나이: 25
Press any key to continue

 

 

사용자의 재정의가 필요한 복사 생성자

복사 생성자는 컴파일러가 자동으로 생성하기 때문에 동적메모리 할당을 하는 객체의 경우 복사 생성자에 의해 객체를 만들게 되면 동적메모리 할당 해제 시 문제가 발생할 수 있다. 이러한 문제가 발생 될 것이 예상된다면 사용자는 복사 생성자를 직접 만들어 사용할 수 있다.

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
48
49
50
51
52
53
54
55
56
57
//복사 생성자를 직접 정의하여 문제를 해결한 예제
#include <iostream.h>
#include <string.h>
 
class String{
        char *str;
        int len;
    public:
        String(char *);                // 생성자
        ~String();                     // 소멸자
        void cat(String &);            // 전달인자가 객체인 멤버함수
        String(const String &tmp);     // 복사 생성자 재정의
        void prn();
};
 
String::String(char *p) {
    len = strlen(p);
    str = new char[len+1];
    strcpy(str,p);
}
 
String::~String() {
    cout << "Deleting str...\n";
    delete str; // 메모리 해제
}
 
void String::cat(String &s) {
    len = len + s.len;
    char *tmp = new char[len+1];     // 메모리 동적할당
    strcpy(tmp, str);                // 문자열 복사
    strcat(tmp, s.str);              // 문자열 연결
    delete str;                      // 옛 문자열 해제
    str = tmp;
}
 
//복사 생성자 재정의
//복사 생성자는 이미 만들어진 객체를 레퍼런스변수로 받음
String::String(const String &tmp) {
    len = tmp.len;
    str = new char[len+1];
    strcpy(str, tmp.str);
}
 
void String::prn() {
    cout << "문자열: " << str << "(" << len << ")" << endl;
}
 
int main()
{
    String str1("Object-oriented"), str2(str1);
    str1.prn();
    str2.prn();
    str1.cat(str2);
    cout << "\n====문자열 연결====\n");
    str1.prn();
    return 0;
}
cs
//실행결과
문자열: Object-oriented (16)
문자열: Object-oriented (16)

====문자열 연결====
문자열 : Object-oriented Object-oriented (32)
Deleting str...
Deleting str...
Press any key to continue

 

'C++' 카테고리의 다른 글

연산자 오버로딩  (1) 2019.11.27
객체와 friend 함수  (0) 2019.11.27
메모리 구조와 동적 메모리 할당  (0) 2019.11.27
C++이란?  (0) 2019.11.27

+ Recent posts