클래스 내 static
class CObj
{
public:
CObj() //: m_iA(100) (x)
{
//m_iA = 100; (x)
}
public:
static int m_iA; // 클래스 변수(정적 멤버 변수)
클래스 내 static 변수는 어떻게 초기화할까?
생성자로도 이니셜라이저로도 초기화가 불가능하다.
int CObj::m_iA = 0;
초기화하려면 클래스 위 코드처럼 네임스페이스를 이용해서 초기화 해야 한다.
이렇게 초기화하기 어려운데 왜 쓰는 걸까?
정적 멤버는 아무리 객체가 많아도 클래스에 하나만 생성되고 모든 객체에서 접근이 가능하다.
또한 전역변수인데 은닉성을 통해 숨기고 싶을 때 클래스 내부에 static으로 선언하기도 한다.
// 클래스 함수(정적 함수)
static void Print(void)
{
m_iB = 400; // (x) 멤버 변수
m_iA = 400; // (o) 정적 변수
}
...
int main()
{
CObj::Print();
}
클래스 내 static함수 또한 존재한다. 멤버 변수에 접근할 수 없고 정적 변수만 사용할 수 있다.
객체 생성 없이 네임스페이스를 이용해 함수를 호출할 수 있다는 특징이 있다.
복사 생성자
복사 생성자는 객체를 복사 생성할 때 호출되는 생성자로 기본 생성자처럼 디폴트 복사 생성자가 존재한다.
디폴트 생성자는 얕은 복사를 수행한다.
CObj(const CObj& rhs) : m_iA(rhs.m_iA)
{
}
기본형은 매개변수를 const 클래스&로 받고 현재 객체의 멤버 변수의 복사 대상의 멤버 변수 값을 대입한다.
복사 생성자가 사용되는 상황은 세가지가 있다.
void main(void)
{
CObj Temp(100);
CObj Dest(Temp);
}
1.원본 객체를 매개변수로 넣어 객체를 생성할 때
void Print(CObj _Src)
{
_Src.Render();
}
2.함수의 매개변수를 객체로 받을 때 (매개변수는 원래 대입받은 대상을 복사하니까)
CObj Get_Obj() // 3. 함수의 반환 타입이 객체 타입인 경우
{
CObj Test(2000);
return Test;
}
3.함수가 객체 타입으로 반환할 때
함수가 종료될 때 지역적으로 선언한 Test가 삭제되고 Test 객체를 복사한 임시 객체가 반환된다.
반환된 임시객체는 다음 행으로 넘어가면 바로 소멸된다.
class CObj
{
private:
int* m_pA;
public:
CObj()
{
m_pA = new int;
}
CObj(const CObj& rhs)
{
//m_pA = rhs.m_pA; // 얕은 복사(shallow copy)에 의한 메모리 해제 문제 발생
m_pA = new int; // 깊은 복사(deep copy)에 의한 메모리 문제 해결
*m_pA = *rhs.m_pA; //새 메모리 할당 후 값 복사
}
~CObj()
{
delete m_pA;
}
};
복사 생성에도 얕은 복사, 깊은 복사가 있다. 생성자에서 동적할당이 일어날 때 발생하는데,
복사 생성자에서 동적할당한 메모리의 포인터를 주소값만 복사해보자. 이걸 얕은 복사라고 한다.
그럼 rhs를 복사해서 생성한 객체의 m_pA도 rhs.m_pA가 가리키는 메모리를 가리킬 것이다.
그러면 소멸자에서 메모리를 해제할 때 두 객체가 같은 메모리를 가리키고 있으므로 중복해서 메모리를 해제하는 문제가 발생할 것이다. 그래서 복사 생성하는 객체의 멤버가 새로운 메모리를 할당하도록 하는 것이 깊은 복사이다.
'Today I Learned' 카테고리의 다른 글
| 23.02.16 - 정적 바인딩과 동적 바인딩, 가상 함수 (0) | 2023.02.16 |
|---|---|
| 23.02.15 - extern, friend, 상속성 (0) | 2023.02.15 |
| 23.02.13 - 이니셜라이저, const 함수 (0) | 2023.02.13 |
| 23.02.06 ~ 23.02.10 - 객체, 생성자, explicit, 전방선언 (0) | 2023.02.13 |
| 23.02.02 - 파일 입출력2, 매크로, 레퍼런스 (0) | 2023.02.02 |