C++

[강의] 11월 15일 수업정리

k-codestudy 2024. 11. 17. 19:02

어제 배운것에 대한 복습과 만들어주는 상속에 대한 수업을 들었다.

 

1. 복습

1.1 enum의 핵심 개념

  • 숫자에 의미를 부여하는 것이 가장 중요하며, 숫자와 의미의 관계는 두 가지로 나뉜다:
    • 의미가 중요한 경우
      • 예: 고유 ID처럼 서로를 구별하기 위한 목적.
    • 숫자가 중요한 경우
      • 예: π 값을 3으로 고정할 때처럼 값 자체가 중요한 경우.

하지만 대부분의 경우, 구별을 목적으로 사용을 한다.

 

 

1.2 enum 사용의 장점

  • #define 대신 enum 사용
    • #define은 단순히 상수를 정의하는 데 그친다.
    • enum은 명확한 자료형을 제공하므로 의미와 타입이 더 분명하다.
    • 코드를 처음 접하는 상황에서도 무엇을 넣어야 할지 명확하게 알 수 있다.
  • 소속 관계
    • #define은 소속 관계를 표현할 수 없지만, enum은 소속 관계를 나타낼 수 있다.
      • 예: 특정 enum 값들이 하나의 그룹(열거형)에 소속됨을 명확히 알 수 있다.
  • 고유 ID 부여
    • 서로 다른 값들 간의 구분을 위해 enum을 사용하면 직관적이다.

 

1.3 C++의 enum과 enum class의 차이점

  • 기본 enum의 단점
    • 독립적으로 사용할 수 있다 보니 소속 관계가 뚫려 있는 경우가 생긴다.
    • 자동으로 int로 변환되며, 다른 자료형에서도 자유롭게 사용 가능해 타입 안전성이 부족하다.
  • enum class의 장점
    • 소속 관계가 명확하다.
      • 다른 자료형과 섞이는 일이 없어 타입 안전성을 보장한다.
         

1.4 초기화와 enum 사용 시 유의점

  • 초기화 상태 보장
    • C++에서 변수를 유니폼 초기화하면 기본값 0이 들어가지만, 해당 값이 반드시 유효한 값일지는 보장되지 않는다.
    • 따라서 초기값을 명확히 설정하는 것이 좋다.
      • 예: "데이터를 아직 다루지 않았다"는 것을 나타내기 위해 디폴트 값으로 0을 설정.
  • 디폴트 리소스 설정의 중요성
    • 명확한 초기값을 통해 코드의 안정성과 가독성을 높인다.

1.5 결론

  • enum은 의미를 부여하고 구별하기 위해 사용한다.
  • C++에서는 타입 안전성과 명확한 소속 관계를 위해 enum class를 사용하는 것이 권장된다.
  • 초기화와 디폴트 값을 통해 데이터를 다루지 않은 상태를 명확히 표현하고, 안정적인 코드를 작성하는 것이 좋다.

 

2. 만들어주는 상속 

// moveMGR.h
#pragma once 

#include <stdio.h>
#include "move.h"

class C_MOVEMGR
{
public:
	enum class E_TYPE  
	{
		E_NONE = 0,
		E_WALK,
		E_FLY,
		E_SWIM,

		E_MAX

	};
public:
	C_MOVEMGR() = default;
	C_MOVE* createMove(E_TYPE eType); 
	void deleteMove(C_MOVE* pMove);
};

// move.h
#pragma once

#include <stdio.h>

class C_MOVE abstract
{
public:
	C_MOVE() = default;
	virtual ~C_MOVE() = default;
	virtual void move() abstract;
};

class C_WALK : public C_MOVE
{
public:
	void move() override;
};

class C_FLY : public C_MOVE
{
public:
	void move() override;
};

class C_SWIM : public C_MOVE
{
public:
	void move() override;
};


// moveMGR.cpp
#include "moveMGR.h"

C_MOVE* C_MOVEMGR::createMove(E_TYPE eType)
{
    C_MOVE* pMove{};
    if (eType == E_TYPE::E_WALK)
        pMove = new C_WALK{};
    if (eType == E_TYPE::E_FLY)
        pMove = new C_FLY{};
    if (eType == E_TYPE::E_SWIM)
        pMove = new C_SWIM{};
    
    
    return pMove;
}

void C_MOVEMGR::deleteMove(C_MOVE* pMove)
{
    delete pMove;
    pMove = nullptr;
}

	
// move.cpp
#include "move.h"

void C_WALK::move()
{
	printf("걷다\n");
}

void C_FLY::move()
{
	printf("날다\n");
}

void C_SWIM::move()
{
	printf("수영하다\n");
}


// main.cpp
#include <iostream>
#include "moveMGR.h"

int main()
{

	C_MOVE* pMove{};
	C_MOVEMGR cMgr{};

	pMove = cMgr.createMove(C_MOVEMGR::E_TYPE::E_FLY);
	pMove->move();
	pMove = cMgr.createMove(C_MOVEMGR::E_TYPE::E_SWIM);
	pMove->move();
	pMove = cMgr.createMove(C_MOVEMGR::E_TYPE::E_WALK);
	pMove->move();

	cMgr.deleteMove(pMove);

}