들어가기에 앞서...
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 |