1. 동적 객체의 생성 및 소멸

  • new 키워드로 객체 동적 생성, delete 키워드로 객체 소멸(생성자, 소멸자 호출)
  • 생성자와 소멸자의 호출 시점을 잘 알아야 함
  • 배열로 생성한 객체는 반드시 배열로 삭제(배열로 삭제하지 않을 경우 배열 첫 번째 요소만 삭제)
#include <iostream>
using namespace std;

class CTest
{
private:
    int m_nData;

public:
    CTest()
    {
        cout << "CTest::CTest()" << endl;
    }

    ~CTest()
    {
        cout << "~CTest::CTest()" << endl;
    }
};

int main()
{
    cout << "Begin" << endl;

 // new 연산자를 이용해 객체 생성
 // CTest `*pData` = new CTest;
    cout << "Test" << endl;

 // delete 연산자를 이용해 객체 삭제
    delete pData;
    cout << "End" << endl;

    CTest `*pData` = new CTest[3];

    delete[] pData;

    cout << "End" << endl;

    return 0;
}
// 실행결과
// Begin
// CTest::CTest()
// CTest::CTest()
// CTest::CTest()
// ~CTest::CTest()
// ~CTest::CTest()
// ~CTest::CTest()
// End


2. 참조(Reference) type 멤버 초기화

  • class 멤버변수도 참조 type으로 선언 가능
  • 참조자는 반드시 선언과 동시에 초기화 되어야 함
  • 멤버 이니셜라이저(Member Initializer)에 의해 초기화
#include <iostream>
using namespace std;

class CTest
{
private:
    // 참조자 타입의 멤버변수
    int &m_Data;
public:

    // 참조자 타입의 멤버변수는 반드시 객체 생성과 동시에 초기화 되어야 한다!
    // (참조자는 선언과 동시에 초기화 되어야 하기 때문에)
    CTest(int &nParam) : m_Data(nParam)
    {
        // empty
    }

    int GetData()
    {
        return m_Data;
    }

};

int main()
{
    int num = 10;
    // 객체 생성 및 생성자에 인자값 전달을 통해 초기화
    CTest test(num);

    cout << test.GetData() << endl;

    // 참조 원본값 수정 후 결과
    num = 20;
    cout << test.GetData() << endl;

    return 0;
}

// 실행 결과
// 10
// 20


3. 생성자 오버로딩

  • 생성자도 함수이기 때문에 오버로딩 가능
  • 생성자를 오버로딩 할 경우 중복된 코드를 작성하기 때문에 비효율적
  • C++11에는 생성자 위임이 가능(생성자에서 이미 정의된 생성자 호출 가능)
  • 생성자 위임 예시 코드 CMyPoint(int x, int y) : CMyPoint(x)
#include <iostream>
using namespace std;

class CMyPoint
{
private:
    int m_x = 0;
    int m_y = 0;
public:
    CMyPoint(int x)
    {
        cout << "CMyPoint(int)" << endl;
        // x 값이 100을 넘는지 검사, 넘을 경우 100으로 값 고정
        if(x > 100)
            x = 100;

        m_x = x;
    }

    // C++11에서는 생성자에서 이미 정의된 생성자를 호출하여 멤버변수 초기화 가능
    CMyPoint(int x, int y) : CMyPoint(x)
    {
        cout << "CMyPoint(int, int)" << endl;

        // y값 검사 후 200이 넘으면 200으로 값 고정
        if(y > 200)
            y = 200;

        m_y = y;
    }

    void Print()
    {
        cout << "X: " << m_x << endl;
        cout << "Y: " << m_y << endl;
    }
};

int main()
{
    CMyPoint ptBegin(110);
    ptBegin.Print();

    CMyPoint ptEnd(50, 250);
    ptEnd.Print();

    return 0;
}

// 실행결과
// CMyPoint(int)
// X: 100
// Y: 0
// CMyPoint(int) --> 매개변수가 2개인 생성자에서 매개변수가 1개인 생성자를 호출
// CMyPoint(int, int)
// X: 50
// Y: 200


4. 명시적 Default 생성자

  • default 키워드를 통해 명시적으로 Default 생성자 선언 & 정의
  • Default 생성자를 구현하지 않고 새로운 생성자를 구현할 경우 Default 생성자는 사라진다.
    • delete 키워드를 통해 Default 생성자의 삭제를 명시할 수 있다.
    • ex) CTest() = delete;
#include <iostream>
using namespace std;

class CTest
{
public:
    int m_nData = 5;
    // 함수의 선언과 정의는 분리하는 것이 효율적일 때가 많다.
    // CTest();

    // default 키워드를 사용하면 Default 생성자의 선언과 정의를 한 번에 처리할 수 있다.
    CTest() = default;

};

// class 외부에 Default 생성자 정의
//CTest::CTest()
//{
//    // empty
//}

int main()
{
    CTest a;
    cout << a.m_nData << endl;

    return 0;
}


본 포스팅 내용은 이것이 C++이다를 학습한 내용을 바탕으로 요약한 글입니다. 코드에 문제가 있을 수 있으며 다소 부정확한 내용이 있을 수 있으니 참고하시기 바랍니다. 잘못된 내용이 있다면 덧글로 남겨주시면 내용을 반영하여 수정하도록 하겠습니다. 감사합니다.



[Reference]

[1] 이것이 C++이다, p.125-135