클래스를 정의하는 부분을 만든다.
해당 헤더에서 만든 클래스는 추후 멤버메소드를 정의할 때 사용한다.
#pragma once
class CArr {
private :
//해당 변수는 직접 수정 할 수 없도록 private로 정의한다.
//또한 멤버변수의 주소를 참조하기 위해 포인터 변수로 생성한다.s
int* m_int;
int m_iCount;
int m_MaxCount;
//생성자와 소멸자를 만들어서 최초 초기화 시 원하는 멤버변수의 값을 사용하도록 한다.
public :
// 생성자
CArr();
//소멸자
~CArr();
// 구현은 Carr.cpp에서 진행한다.
public :
// 배열을 추가하는 함수이다.
void PushBack(int Data);
// 배열을 추가할 때 공간을 늘려주는 함수이다.
void resize(int DataCount);
};
멤버변수 int는 실제 값이 들어갈 변수이고
iCount변수는 들어간 값의 갯수
MaxCount는 현재 들어간 값의 총 갯수를 의미한다.
//다른 파일에 있는 클래스 내부에서 가져온 클래스를 정의한다.
CArr::CArr() :
m_int(nullptr),
m_iCount(0),
m_MaxCount(0)
{
// new 생성자를 사용하여 m_int에 공간을 할당한다.
// new로 생성해야 클래스의 크기만큼 공간이 할애된다.
m_int = new int[2];
}
CArr::~CArr(){
//cpp에서는 delete를 사용해서 메로리를 해제하는데 여러개일 경우 []를 붙여서 사용한다.
// delete를 붙여서 주소가 연속적이라는 것을 알려준다.
delete[] m_int;
}
void CArr::PushBack(int Data){
//this 생략 가능하다.
//힙 영역 공간이 다참
if(this->m_MaxCount <= this->m_iCount){
//재할당
resize(m_MaxCount * 2);
}
//데이터 추가
this->m_int[this->m_iCount++] = Data;
}
void CArr:: resize(int DataCount){
// 추가하려는 데이터가 현재 데이터 갯수보다 작거나 같으면 의미가 없다.
if(this->m_MaxCount >= DataCount){
assert(this->m_MaxCount >= DataCount);
}
//리사이즈 시킬 갯수만큼 동적할당
// 멤버변수에 주소값을 전달하여 pNew를 사용하기 위해 포인터 변수로 공간을 생성한다.
int* pNew = new int[DataCount];
//기존 공간 데이터들을 새로 할당된 공간으로 복사
for(int i =0; i< m_iCount; ++i){
pNew[i] = m_int[i];
}
// 기존 공간 삭제
delete[] m_int;
//배열이 새로 할당된 공간을 가르킨다.
m_int = pNew;
//MaxCount 변경점 적용
m_MaxCount = DataCount;
}
#include <iostream>
#include "Arr.h"
int main() {
//c++동적할당 new, delete
//기존은 malloc과 free는 내가 순수하게 요청한 것만 크기를 할당하였다.
CArr carr;
carr.PushBack(10);
carr.PushBack(20);
carr.PushBack(30);
//소멸자를 호출하여 메모리에서 자동 해제 한다.
return 0;
}
이제 데이터를 넣고 관리하는 클래스가 완성되었다.
그러나 일반적인 배열처럼 동작하지 않는다. 우리가 원하는 것은 배열과 같이 carr[1]도 사용가능하고 carr[1] = 1; 처럼 값을 할당 할 수도 있어야 한다. 클래스의 오퍼레이션 연산자를 통해서 만들어보자
#pragma once
class CArr {
private :
int* m_int;
int m_iCount;
int m_MaxCount;
public :
// 생성자
CArr();
//소멸자
~CArr();
// 구현은 Carr.cpp에서 진행한다.
public :
void PushBack(int Data);
void resize(int DataCount);
// 오퍼레이션 연산자 추가하기
void operator[] (int idx);
};
오퍼레이션 연산자를 정의한다.
레퍼런스로 값을 전달해야 즉시 수정할 수 있는 배열 할당이 가능하다.
//주소로 전달하면 역참조하여서 원본 배열을 수정 할 수 있다.
//레퍼런스로 전달해야 해당 값을 즉시 수정이 가능하다.
int& CArr::operator[](int idx){
// []를 사용하면 m_int[idx]를 실행시켜라.
return m_int[idx];
}
오퍼레이션 연산자를 추가하면 다음과 같은 동작이 가능하다.
#include <iostream>
#include "main.h"
int main() {
//c++동적할당 new, delete
//기존은 malloc과 free는 내가 순수하게 요청한 것만 크기를 할당하였다.
CArr carr;
carr.PushBack(10);
carr.PushBack(20);
carr.PushBack(30);
//소멸자를 호출하여 메모리에서 자동 해제 한다.
//원래 객체의 배열을 호출 할 때 다음은 실행되지 않는다.
// carr[0];
//그러나 연산자 함수를 만들어서 임의로 만들어 줄 수 있다.
int dataArr = carr[2];
carr[2] =530;
std::cout<<carr[2]<<std::endl<<dataArr <<std::endl;
return 0;
}
출력문을 통해 결과를 보면 최초 클래스 메소드를 이용하여 배열을 추가하고 해당되는 배열의 자리를 530 값을 추가하니 즉시 값이 반영된 것을 알 수 있다.