[C++] 캐스팅, N차원 배열 만들기

·2023년 8월 22일
0

C++

목록 보기
10/17
post-custom-banner

C++ 스타일의 캐스팅

기존의 C언어 캐스팅 방법 : 암시적, 명시적 캐스팅

  • 명시적 캐스팅은 말도 안되는 캐스팅에 컴파일러가 오류를 발생시키지 않음
    (프로그래머의 실수에 취약)
  • 명시적 캐스팅은 코드의 가독성이 떨어짐 (예) function((int)variable);

C++의 캐스팅 방법

(1) static_cast : 언어적 차원에서 지원하는 일반적인 타입 변환
(2) const_cast : 객체의 상수성(const)를 없애는 타입 변환 (예) const int -> int
(3) dynamic_cast : 파생 클래스 사이에서의 다운 캐스팅
(4) reinterpret_cast : 위험을 감수하고 하는 캐스팅 (예) 서로 연관이 없는 포인터들 사이의 캐스팅

사용 방법
(원하는 캐스팅 종류)<바꾸려는 타입>(무엇을 바꿀 것인가?)

// 예
static_cast<int>(float_variable); // C 언어의 (int)(float_variable)와 동일

N차원 배열 만들기

#include <iostream>

namespace MyArray
{
	class Array;
	class Int;

	class Array 
	{
		friend Int;

		const int dim;  // 몇 차원 배열 인지
		int* size;  // size[0] * size[1] * ... * size[dim - 1] 짜리 배열이다.

		struct Address
		{
			int level;
			// 맨 마지막 레벨(dim - 1 레벨) 은 데이터 배열을 가리키고, 그 위 상위
			// 레벨에서는 다음 Address 배열을 가리킨다.
			void* next;
		};

		Address* top;

	public:
		Array(int dim, int* array_size) : dim(dim)
		{
			size = new int[dim];
			for (int i = 0; i < dim; i++) size[i] = array_size[i];

			top = new Address;
			top->level = 0;

			initialize_address(top);
		}

		Array(const Array& arr) : dim(arr.dim)
		{
			size = new int[dim];
			for (int i = 0; i < dim; i++) size[i] = arr.size[i];

			top = new Address;
			top->level = 0;

			initialize_address(top);
			// 내용물 복사
			copy_address(top, arr.top);
		}

		void copy_address(Address* dst, Address* src) 
		{
			if (dst->level == dim - 1) 
			{
				for (int i = 0; i < size[dst->level]; ++i)
					static_cast<int*>(dst->next)[i] = static_cast<int*>(src->next)[i];
				return;
			}
			for (int i = 0; i != size[dst->level]; i++) 
			{
				Address* new_dst = static_cast<Address*>(dst->next) + i;
				Address* new_src = static_cast<Address*>(src->next) + i;
				copy_address(new_dst, new_src);
			}
		}

		// address 를 초기화 하는 함수이다. 재귀 호출로 구성되어 있다.
		void initialize_address(Address* current) 
		{
			if (!current) return;
			if (current->level == dim - 1) 
			{
				current->next = new int[size[current->level]];
				return;
			}

			current->next = new Address[size[current->level]];

			for (int i = 0; i != size[current->level]; i++) 
			{
				(static_cast<Address*>(current->next) + i)->level = current->level + 1;
				initialize_address(static_cast<Address*>(current->next) + i);
			}
		}
		void delete_address(Address* current) 
		{
			if (!current) return;

			for (int i = 0; current->level < dim - 1 && i < size[current->level]; i++) 
			{
				delete_address(static_cast<Address*>(current->next) + i);
			}

			if (current->level == dim - 1) 
			{
				delete[] static_cast<int*>(current->next);
			}

			delete[] static_cast<Address*>(current->next);
		}

		Int operator[](const int index);

		~Array() 
		{
			delete_address(top);
			delete[] size;
		}
	};
	class Int {
		void* data;

		int level;
		Array* array;

	public:
		Int(int index, int _level = 0, void* _data = NULL, Array* _array = NULL)
			: level(_level), data(_data), array(_array) {
			if (_level < 1 || index >= array->size[_level - 1]) 
			{
				data = NULL;
				return;
			}
			if (level == array->dim) 
			{
				// 이제 data 에 우리의 int 자료형을 저장하도록 해야 한다.
				data = static_cast<void*>((
					static_cast<int*>(static_cast<Array::Address*>(data)->next) + index));
			}
			else 
			{
				// 그렇지 않을 경우 data 에 그냥 다음 addr 을 넣어준다.
				data = static_cast<void*>(static_cast<Array::Address*>(
					static_cast<Array::Address*>(data)->next) +
					index);
			}
		};

		Int(const Int& i) : data(i.data), level(i.level), array(i.array) {}

		operator int() 
		{
			if (data) return *static_cast<int*>(data);
			return 0;
		}

		Int& operator=(const int& a) 
		{
			if (data) *static_cast<int*>(data) = a;
			return *this;
		}

		Int operator[](const int index) 
		{
			if (!data) return 0;
			return Int(index, level + 1, data, array);
		}
	};


	Int Array::operator[](const int index) 
	{
		return Int(index, 1, static_cast<void*>(top), this);
	}
}

int main() {
	int size[] = { 2, 3, 4 };
	MyArray::Array arr(3, size);

	for (int i = 0; i < 2; i++) 
	{
		for (int j = 0; j < 3; j++)
		{
			for (int k = 0; k < 4; k++) 
			{
				arr[i][j][k] = (i + 1) * (j + 1) * (k + 1);
			}
		}
	}
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			for (int k = 0; k < 4; k++)
			{
				std::cout << i << " " << j << " " << k << " " << arr[i][j][k]
					<< std::endl;
			}
		}
	}
}

실행 결과
0 0 0 1
0 0 1 2
0 0 2 3
0 0 3 4
0 1 0 2
0 1 1 4
0 1 2 6
0 1 3 8
0 2 0 3
0 2 1 6
0 2 2 9
0 2 3 12
1 0 0 2
1 0 1 4
1 0 2 6
1 0 3 8
1 1 0 4
1 1 1 8
1 1 2 12
1 1 3 16
1 2 0 6
1 2 1 12
1 2 2 18
1 2 3 24

post-custom-banner

0개의 댓글