C++

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

k-codestudy 2024. 11. 15. 03:38

오늘은 빌려주는 방법의 상속과 enum, enum class에 대한 수업을 들었다.

1. eunm 

1.1 eunm 정의 

enum은 여러 상수 값을 열거하고 이를 정수형 상수로 매핑하는 방식으로, 컴파일러는 열거형 멤버들을 정수형 상수로 인식한다. 이로 인해 enum 형식의 변수는 인덱싱에 사용할 수 있으며, 산술 연산이나 관게 연산의 피연산자로 활용될 수 있다.

 

1.2 예시 

enum
{
	E_TEST_A,
	E_TEST_B,
	E_TEST_C,
	E_TEST_D
};

 

enum은 숫자에 의미를 부여하여 독립적인 id를 만드는데 사용된다.

#define과 달리 enum은 열거형 멤버의 의미를 알수 있는 네임스페이스 기능을 제공하며 일반적으로 구조체나 클래스는 이름을 부여 정의하지만 enum은 이름을 생략 가능하다. 
각 멤버는 기본적으로 0부터 순차적으로 값을 가지며, 특정 멤버에 값이 할당되면 이후 멤버는 해당 값을 기준으로 증가하게 된다. 예를 들어 E_TEST_A에 100을 할당하면 E_TEST_B는 101이 된다.

 

1.3 enum 주의사항

  • enum은 특정 값이 반복될 가능성이 있으며, 값이 겹칠 경우에도 서로 독립된 ID를 보장하지 않는다. 예를 들어 E_TEST_A = 100, E_TEST_B = 101, E_TEST_C = 100으로 설정하면, 같은 값을 가지는 멤버가 생성된다.
  • 유니폼 초기화 시 값이 0으로 설정될 수 있으며, 잘못된 초기화가 발생할 수 있으므로 기본값이 0이 되도록 설정하는 것이 좋다. 예를 들어, E_NONE = 0으로 지정하여 안전한 초기화를 보장하는 것이 중요하다. 만약 디폴트 초기값( E_NONE = 0;)을 보장하지 않으면 프로그램이 터지는 일도 발생할수있다.

 

2. enum class

 

2.1 설명 

기존 enum은 열거형의 네임스페이스가 부족하여 다른 enum과 중복된 이름의 변수가 있을 때 어떤 enum에 속하는지 컴파일러가 구분하기 어려웠다. 이를 해결하기 위해 enum class가 도입이 되었다.

enum 선언에 calss 키워드를 붙히면 enum class로 사용할 수 있으며 enum class는 네임스페이스 기능을 제공하여 열거형 이름을 통해 명확하게 구분할 수 있다. enum class의 맴버는 열거형 이름::열거자 형식으로 호출해야 한다.

 

2.2 예시 

#include <iostream>

void func(E_TEST eTest);

enum class E_TEST
{
	E_NONE = 0,
	E_TEST_A,
	E_TEST_B,
	E_TEST_C,
	E_TEST_D
};

int main()
{
	E_TEST eTest{};

	eTest = E_TEST::E_TEST_A;

	printf("%d\n", eTest);

	func(E_TEST::E_TEST_C);
}

void func(E_TEST eTest)
{
}

 

2.3 일반 enum과 enum class의 차이점

  1. 명확한 네임스페이스: enum class는 네임스페이스를 포함하여, 다른 열거형과 멤버 이름이 겹치더라도 구분이 가능하다. 예를 들어 eTest = E_TEST::E_TEST_A;처럼 반드시 enum 이름을 지정해야 합니다.
  2. 0값 초기화: enum과 마찬가지로 안전한 초기화를 위해 0 값 멤버를 첫 번째로 지정하는 것이 좋다. (디폴트 초기값 보장)
  3. 타입 안전성: enum class는 int와 호환되지 않으며, 필요시 캐스팅을 통해 정수형으로 변환해야 합니다. 일반 enum은 암묵적으로 int와 호환됩니다.
  4. #define과의 차이점: #define은 소속 관계가 없고 단순한 상수 매크로로 작동합니다. enum class는 네임스페이스 기능을 통해 상수를 안전하고 명확하게 관리할 수 있어 더 선호된다.

 

3. 오리 클래스, 상속을 사용하여 3가지 오리 종류와 소리를 출력하는 프로그램

// duck.h
#pragma once

class C_MOVE;
class C_SOUND;

class C_DUCK
{
private:
	C_MOVE* m_cMove;
	C_SOUND* m_cSound;
public:
	C_DUCK() = default;
	void init(C_SOUND* pSound, C_MOVE* pMove);
	C_MOVE* getmove();
	C_SOUND* getSound();
};

// move.h
#pragma once
#include <stdio.h>

__interface I_MOVE
{
	void move();
};

class C_MOVE : public I_MOVE
{
public:
	C_MOVE() = default;
	virtual ~C_MOVE() = default;
};

// sound.h
#pragma once
#include <stdio.h>

__interface I_SOUND
{
	void sound();
};

class C_SOUND : public I_SOUND
{
public:
	C_SOUND() = default;
	virtual ~C_SOUND() = default;
};

// fly.h
#pragma once

#include "move.h"

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

// swim.h
#pragma once

#include "move.h"

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

// walk.h
#pragma once

#include "move.h"

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

// sound1.h
#pragma once

#include "sound.h"

class C_SOUND1 : public C_SOUND
{
public:
	void sound() override;
};

// sound2.h
#pragma once

#include "sound.h"

class C_SOUND2 : public C_SOUND
{
public:
	void sound() override;
};

// sound3.h
#pragma once

#include "sound.h"

class C_SOUND3 : public C_SOUND
{
public:
	void sound() override;
};

 

// duck.cpp
#include "duck.h"

void C_DUCK::init(C_SOUND* pSound, C_MOVE* pMove)
{
	m_cMove = pMove;
	m_cSound = pSound;
}

C_MOVE* C_DUCK::getmove()
{
	return m_cMove;
}

C_SOUND* C_DUCK::getSound()
{
	return m_cSound;
}

// fly.cpp
#include "fly.h"

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

// swim.cpp
#include "swim.h"

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

// walk.cpp
#include "walk.h"

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

// sound1.cpp
#include "sound1.h"

void C_SOUND1::sound()
{
	printf("파닥파닥 ");
}

// sound2.cpp
#include "sound2.h"

void C_SOUND2::sound()
{
	printf("첨벙첨벙 ");
}

// sound3.cpp
#include "sound3.h"

void C_SOUND3::sound()
{
	printf("후다닥 ");
}

// main.cpp
#include <iostream>
#include "duck.h"
#include "fly.h"
#include "swim.h"
#include "walk.h"
#include "sound1.h"
#include "sound2.h"
#include "sound3.h"


int main()
{
	C_FLY cFly{};
	C_SWIM cSwim{};
	C_WALK cWalk{};
	C_SOUND1 cSound1{};
	C_SOUND2 cSound2{};
	C_SOUND3 cSound3{};

	C_DUCK arDuck[5]{};
	arDuck[0].init(&cSound1, &cFly);
	arDuck[1].init(&cSound2, &cSwim);
	arDuck[2].init(&cSound3, &cWalk);
	arDuck[3].init(&cSound2, &cSwim);
	arDuck[4].init(&cSound3, &cWalk);

	for (int i = 0; i < 5; i++)
	{
		arDuck[i].getSound()->sound();
		arDuck[i].getmove()->move();
	}

}

4. Enum Class를 이용한 대여 시스템 관리 매니저 구현하기 

// moveMGR.h
#pragma once

#include "move.h"

class C_MOVE;

class C_MOVEMGR
{

public:
	enum class E_TYPE
	{
		E_NONE = 0, // 반드시 보장할것
		E_WALK,
		E_FLY,
		E_SWIM,

		E_MAX  // 사용하는 용도는 아님 -> 최대 갯수를 파악하기 위한것
	};
private:
	C_MOVE* m_arMove[(int)E_TYPE::E_MAX];

public:
	C_MOVEMGR() = default;
	void init();
	C_MOVE* getMove(E_TYPE eType);
	void release();
};

// move.h
#pragma once
#include <stdio.h>

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

// walk.h
class C_WALK : public C_MOVE
{
public:
	void move() override;
};

// fly.h
class C_FLY : public C_MOVE
{
public:
	void move() override;
};

// swim.h
class C_SWIM : public C_MOVE
{
public:
	void move() override;
};


// moveMGR.cpp
#include "moveMgr.h"
#include "move.h" // 알아야 동작을 시키기에 넣어야함

void C_MOVEMGR::init()
{
	m_arMove[(int)E_TYPE::E_FLY] = new C_FLY{};
	m_arMove[(int)E_TYPE::E_SWIM] = new C_SWIM{};
	m_arMove[(int)E_TYPE::E_WALK] = new C_WALK{};
}

C_MOVE* C_MOVEMGR::getMove(E_TYPE eType)
{
	return m_arMove[(int)eType];
}

void C_MOVEMGR::release()
{
	for (int i = 0; i < (int)E_TYPE::E_MAX; i++)
	{
		if (m_arMove[i])
		{
			delete m_arMove[i];
			m_arMove[i] = nullptr;
		}
	}
}

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

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

// fly.cpp
void C_FLY::move()
{
	printf("난다\n");
}

// swim.cpp
void C_SWIM::move()
{
	printf("수영\n");
}

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

int main()
{
	C_MOVEMGR cMgr{};
	C_MOVE* pMove{};

	cMgr.init();
	pMove = cMgr.getMove(C_MOVEMGR::E_TYPE::E_FLY);
	pMove->move();

	cMgr.release();
}

이건 하나하나 다시 생각하면서 해볼것 

'C++' 카테고리의 다른 글

[강의] 11월 19일 수업정리  (0) 2024.11.20
[강의] 11월 15일 수업정리  (0) 2024.11.17
[강의] 11월 13일 수업정리  (2) 2024.11.14
[강의] 11월 12일 수업정리  (6) 2024.11.13
[강의] 11월 8일 수업정리  (1) 2024.11.10