본문 바로가기

프로그래밍 언어/열혈 C++

04-3 생성자와 소멸자 by 윤성우의 열혈 C++

생성자

  • 클래스의 이름과 함수의 이름이 동일하다.
  • 반환형이 선언되있지 않으며 실제로 반환하지 않는다.
  • 객체 생성시 딱 한번 호출된다.
class Simple
{
private:
    int num;
public:
    Simple(int n)
    {
        num = n;
    }
};

int main()
{
    Simple sp(30);
    sp.PrintNum();

    return 0;
}

객체 생성은 Simple sp(30) 으로 생성자에게 전달할 인자의 정보를 추가해야함

  • 함수의 특징을 가지고 있다.

ex) 오버로딩(매개변수 개수만 다르다면 같은 이름으로 선언가능한것) 가능, 매개변수 디폴트 값 설정 가능

  • 매개변수가 선언되있지 않을때 아래와 같은 코드가 가능하다.

Simple sp(30)

Simple sp

Simple * ptr1 = new Simple;

Simple * ptr1 = new Simple();

Simple sp(); // 불가능
// 함수의 선언과 같아 컴파일러가 객체생성문인지 함수의 원형선언인지 구분할 수 없다.
  • 생성자를 정의하지 않으면 '디폴트 생성자'라는게 자동으로 삽입되어 호출된다. 생성자는 없을 수 없다.

멤버 이니셜라이저 (Member Initializer)

  • 이니셜라이저를 이용하면 선언과 동시에 초기화가 이뤄지는 형태로 바이너리 코드가 생성된다.
    따라서 const 멤버변수를 초기화하거나 참조자를 멤버변수로 선언할 수 있다.
class BBB
{
private:
	AAA &ref;
    const int #
    
public:
	BBB(AAA &r, const int &n)
    		: ref(r), num(n)
    {
    }
}

디폴트 생성자

  • 디폴트 생성자는 생성자가 없을때 디폴트 생성자가 삽입되어 생성자가 호출되지 않는 객체가 없도록 한다.

생성자가 있을때는 디폴트 생성자가 생기지 않는데

class Simple
{
private:
	int num;
public:
	Simple(int n) : num(n){}
}

위와 같은 class에서는 다음과 같은 코드로 객체생성이 불가능하다.

// 불가능한 코드
Simple simObj;
Simple * simPtr = new Simple;

위가 가능하게 하려면 Simple() : num(0) { } 과 같은 생성자를 추가해야한다.


private 생성자

#include <iostream>

using namespace std;

class AAA
{
private:
    int num;
public:
    AAA() : num(0) {}
    AAA& CreateInitObj(int n) const
    {
        AAA * ptr = new AAA(n);
        return *ptr;
    }
    void ShowNum() const { cout << num << endl;}
private:
    AAA(int n) : num(n) {}
};

int main()
{
    AAA base;
    base.ShowNum();

    AAA &obj1 = base.CreateInitObj(3);
    obj1.ShowNum();

    AAA&obj2 = base.CreateInitObj(12);
    obj2.ShowNum();


    delete &obj1;
    delete &obj2;
    return 0;
}

위 예제는 private로 선언된 생성자를 통해서 객체를 생성했다.

이를 통해 객체의 생성방법을 제한하고자 하는 경우 유용하게 사용할 수 있다.


소멸자

  • 객체생성시 반드시 호출되는 것이 생성자라면 객체소멸시 반드시 호출되는 것은 소멸자이다.
  • 클래스의 이름 앞에 '~'가 붙은 형태의 이름을 갖는다.
  • 반환형이 선언되어 있지 않으며 실제로 반환하지 않는다
  • 매개변수는 void형으로 선언되어야 한다. (따라서 오버로딩과 디폴트 값 설정 불가능)
#include <iostream>
#include <cstring>

using namespace std;

class Person
{
private:
    char * name;
    int age;
public:
    Person(char * myname, int myage)
    {
        int len = strlen(myname)+1;
        name = new char[len];
        strcpy(name, myname);
        age = myage;
    }
    void ShowPersonInfo() const
    {
        cout << "이름: " << name << endl;
        cout << "나이: " << age <<endl;
    }
    ~Person()
    {
        delete []name;
        cout << "Destructor!!" << endl;
    }
};

int main()
{
    Person boom("Boom", 25);
    boom.ShowPersonInfo();

    return 0;
}