반응형

 

들어가기에 앞서...

const

- const 변수 : 해당 변수를 정보 변경이 불가능한 상수로 변환.

- const 함수 : 해당 함수에서 const의 위치에 따라 정보의 변환을 막거나 반환값을 상수로 바꾼다.

1. const 변수

void main()
{
    const int i = 10;
    i = 20;	//에러 발생
}
  • 선언 하는 순간의 초기화 값 이외에 다른 값을 대입하려하면 에러가 발생한다.

 

2. const 함수

class ConstClass
{
private:
    int iMember;
public:
    ConstClass() { }
    void SetNum(int i) const
    {
        iMember = i;	//에러발생
    }
};
  • 함수의 뒤에 const가 붙으면 해당 함수의 블럭에서 값의 변경이 불가능하다.
class ConstClass
{
private:
    int iMember;
public:
    ConstClass() { }
    const int* GetNum()
    {
        return &iMember;
    }
};

void main()
{
    ConstClass constClass;
    *(constClass.GetNum()) = 100;	//에러발생
}
  • 함수의 반환형 앞에 const가 붙으면 반환한 값에 대한 변경이 불가능하다.

 

 

 

생성자

- 클래스 객체가 만들어질때 자동으로 단 한번 호출되는 함수

- 반환값이 없고, 클래스명과 동일한 이름으로 함수를 만든다.

- 객체의 멤버변수를 초기화하는 목적으로 사용된다.

- 생성자도 함수의 일종이기 때문에 오버로딩이 가능하다.

- 매개변수에 default값을 설정할 수 있다.

#include <iostream>
using namespace std;

class Test
{
private:
    int aMember, bMember;
public:
    Test()
    {
        aMember = 5;
        bMember = 10;
    }
    Test(int a, int b)
    {
        aMember = a;
        bMember = b;
    }
    int GetA() { return aMember; }
    int GetB() { return bMember; }
};

void main()
{
    Test t;
    cout << "Test.a : " << t.GetA() << ", Test.b : " << t.GetB() << endl;
    
    //결과 : Test.a : 5, Test.b : 10
    
    Test t2(20, 30);
    cout << "Test.a : " << t2.GetA() << ", Test.b : " << t2.GetB() << endl;
    
    //결과 : Test.a : 20, Test.b : 30
}

 

※ 생성자를 호출할 때 주의할 점

- 생성자는 다음과 같이 호출할 수 있다.

  • Class Class
  • Class* ptrClass = new Class;
  • Class* ptrClass = new Class();

- 다음과 같은 생성자는 호출할 수 없다. (컴파일 에러가 발생한다.)

  • Class Class()

Why?

- Class Class()를 생성자의 호출 문으로 인정해 버리면, 컴파일러는 이러한 문장을 만났을 때, 이것이 객체생성문인지 함수호출문인지 구분할 수 없게되기 때문에 이러한 유형의 문장은 함수 호출에만 사용하기로 약속되어있다.

 

 

 

복사 생성자

- 동일한 클래스형의 다른 객체의 정보를 복사하여 새로운 객체를 만든다.

- 일반 변수를 초기화 할 때 다른 변수의 값을 이용하는 경우와 같다.

class Test
{
private:
    int iMember;
public:
    Test(int i)
    {
        iMember = i;
    }
    Test(Test& t)
    {
        iMember = t.iMember;
    }
    int GetNum() { return iMember; }
};

void main()
{
    Test t1(20);
    Test t2(t1);
    cout << t1.GetNum() << endl;
    cout << t2.GetNum() << endl;
    
    //결과
    //20
    //20
}

 

※ 디폴트 복사 생성자

- 복사생성자는 정의하지 않아도, 멤버대 멤버의 복사를 진행하는 디폴트 복사 생성자가 자동으로 삽입된다.

class Test
{
private:
    int iMember;
public:
    Test(int i)
    {
        iMember = i;
    }
};

void main()
{
    Test t1(20);
    Test t2(t1);
}
  • Test 클래스에 복사생성자를 정의하지 않아도t2(t1)이 문제없이 컴파일된다.
  • Test t2 = t1;으로 초기화를 시도해도 묵시적 변환으로 인해Test t2(t1);으로 변환되어서 객체가 생성된다.

- 묵시적 변환으로 인해 복사 생성자가 호출되는것을 막으려면 복사 생성자 앞에 explicit 키워드를 붙이면 대입 연산자를 이용한 객체의 생성 및 초기화는 불가능해진다.

  ※ 묵시적 변환은 복사 생성자에서만 일어나는것이 아니라 전달인자가 하나인 생성자가 있다면, 이 역시 묵시적 변환이 발생한다.

 

 

 

콜론 초기화 (멤버 이니셜라이저)

- 해당 생성자의 몸체보다 먼저 매개변수를 받아 초기화하는 방법

- 클래스 멤버변수 중에서 변수 선언과 동시에 초기화 해야하는 변수(ex. const)에 사용

class Test
{
private:
    const int iMember;
public:
    Test(int i) : iMember(i) { }
}
  • const로 선언한 iMember의 값을 생성자의 몸체에서 초기화하게되면 에러가 발생하지만 멤버 이니셜라이저를 사용하게 되면 const로 선언한 멤버의 초기화가 가능하다.
  • 좀 더 쉽게 설명하자면 다음과 같다.
//클래스에서 멤버 이니셜라이저를 사용했을때.
const int i = 20;
//클래스의 생성자 몸체에서 초기화 했을때.
const int n;
n = 20;

※ 멤버 이니셜라이저를 사용하는 것이 성능상 이점이 있다고는 하나, 요즘같이 하드웨어의 성능이 좋은 시대에서는 큰 의미를 가지지 않는다.

 

 

 

소멸자

- 클래스 객체가 소멸할 때 자동으로 호출되는 함수

- 클래스의 이름 앞에 '~'가 붙는다.

- 매개변수는 void형으로 선언되어야 하기 때문에, 오버로딩과 디폴트 값 설정이 불가능하다.

- 생성자와 마찬가지로 반환값이 없다.

- 객체의 동적할당된 멤버변수를 할당해제하는 목적으로 사용된다.

#include <iostream>
using namespace std;

class Test
{
private:
    int* iMember;
public:
    Test()
    {
        iMember* = new int(20);
    }
    ~Test()
    {
    	cout << "소멸자 호출" << endl;
        delete iMember;
    }
    void Display()
    {
        cout << *iMember << endl;
    }
};

void main()
{
    Test t;
    t.Display();
}

//결과
//20
//소멸자 호출
반응형

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

C++ 복사 생성자 심화  (0) 2021.10.17
C++ 파일 입출력 ofstream, ifstream  (0) 2021.10.16
C++ 동적할당 new, delete  (0) 2021.10.13
C++ 참조자(Reference)  (0) 2021.09.29
C++ 클래스, 객체, 인스턴스  (0) 2021.09.29

+ Recent posts