c++

20210723 사용자 정의 헤더 파일 ~ Template

TIN9 2021. 7. 25.
반응형

안녕하세요 틴구입니다.

오늘은 어떤걸 써볼것이냐!

사용자 정의 헤더파일 부터 class를 구현과 선언을 나뉘어 작성하는법, Template까지 작성해보도록 할게요.

우선 사용자 정의 헤더파일부터 볼까요

사용자 정의 헤더파일

우선 사용자 정의 헤더파일이란 본인이 원하는 코드를 헤더파일에 작성 후 #include로 갖고와 사용하는 방식이다

헤더 파일 우클릭 - 추가 - 새항목 - 헤더 파일 - 원하는 파일명(GameInfo)을 만들면 헤더 파일에 GameInfo.h로 헤더 파일이 생성되는데 예전에 메인 함수에서 쓰던

#include <iostream>

#include <time.h>

를 새로 만든 GameInfo.h에 작성을 해 준다음

main.cpp 파일에서 

#include "GamInfo.h" 로 불러오면

iostream, tim.h를 사용할 수 있습니다.

사용자 정의 헤더파일을 include 할때는 " " 안에 작성해주어야 합니다.

ex)

#include "GameInfo,H"

 

int main()

{

    return 0;

}

class .cpp .h생성

class의 경우 main.cpp에 생성하는 방법말고 따로

.cpp 와 .h 파일을 나누어 선언과 구현파일을 만들 수 있습니다.

헤더파일 우클릭 - 추가 - 클래스를 클릭하면 클래스 추가 라는 창이뜨는데

클래스 이름 = 말 그대로 class 뒤에 붙는 클래스타입 변수 명입니다.

.h = 헤더파일 명

.cpp = cpp파일 명이 되겠습니다.

저의 경우

CPlayer / Player / Player 로 생성해 볼게요.

이렇게 생성을 하게 되면

소스 파일 헤더파일에 각각 Player.cpp Player.h 가 생기게 됩니다

여기서 중요한점은 .cpp파일은 구현부분 .h파일은 선언부분으로 나뉘게 됩니다.

class 코드 구현을 .cpp에다가 작성을하고 .h파일에는 그 구현한걸 선언하고

main.cpp에 선언한 .h파일을 전처리기로 불러오는 방식입니다.

예를들어

Player.h파일에

// #pragma once 는 이 헤더파일을 1번만 포함시키도록 해주는 기능이다.

#pragma once

#include "GameInfo.h"

 

class CPlayer
{
public:
    CPlayer();
    ~CPlayer();

public:
    void Output();
};
란 코드를 생성하고

Player.cpp 파일에

// #include 로 Player.h 파일을 받아온다.

#include "Player.h"

// CPlayer의 클래스 변수타입의 CPlayer()생성자에접근하기 위한 구성
CPlayer::CPlayer()
{
    std::cout << "Player 생성자" << std::endl;
}
// 소멸자에 대한 코드 구성
CPlayer::~CPlayer() 
{
    std::cout << "Player 소멸자" << std::endl;
}
// 멤버함수에 대한 코드 구성
void CPlayer::Output()
{
    std::cout << "Player Output Function" << std::endl;
}

순환참조 및 해결 방법

여기서 중요한점이 나오는데 만약에 헤더파일을 두개 생성후 두 헤더파일끼리 include를 해주었을 경우

무한루프형식을 갖게되어 오류가 생길 수 있습니다.

이때 순환참조를 해결하는 방법이 있는데 그것을 전방선언이라고 합니다

전방 선언이란

두개의 헤더파일이 있을때 둘이 include로 이용하지 않고

아래처럼 CMonster 클래스를 전방선언 하여 CMonster 라는 클래스가 어딘가에 있다 라고 가정하고

사용할 수 있게 한다.
전방선언시 이 타입을 실제로 생성하는것은 불가능하고 이 타입에 대한 메모리 주소만을 사용할 수 있다.
즉, 포인터로만 사용이 가능하다는 것이다.

class CMonster;
class CPlayer
{
public:
    CPlayer();
    ~CPlayer();


public:

    // CMonster m_Monster;  - 사용불가
    CMonster* m_Monster;   // 포인터로만 사용이 가능하다


public:
    void Output();
};

Template

템플릿은 타입을 가변적으로 바꿔줄 때 사용할 수 있는 문법입니다.

형태로는

template <typename 원하는이름>
template <class 원하는이름> 이런 식으로 사용한다.
template <typename T, typename T1> 이런식으로 몇개든 타입을 가변적으로 지정할 수 있다.

template <typename T>
void Output(T Number)
{
    std::cout << Number << std::endl;
}

int main()

{

    Output<int>(100);

 

    return 0;

}

를 출력하면 100이 출력이 됩니다.

template <typename T, typename T1>
void Output(T Number, T1 Number1)
{
    std::cout << Number << std::endl;
    std::cout << Number1 << std::endl;

}

int main()

{

    Output<int>(100, 111);

 

    return 0;

을 출력하게 되면

100 

111이 출력됩니다!

근데 여기서 타입네임을

int main()

{

    Output<float>(3.14f)

    Output<float>(3.111f, 3.1232f)

 

    return 0;

}

를 출력하면

3.14

3.111

3.1232 가 출력이 됩니다.

타입네임 T가 넘버의 타입에 해당하기 때문에 <>이 사이에 어느 타입을 넣느냐,()에 따라 숫자가 달라지게 됩니다

단 <>를 생략할 수도 있습니다

int main()

{

    Output(999);

 

    reutrn 0;

}

의 형태로 코드를 구성하면 <>타입을 생략하고 ( )사이가 무엇이느냐에 따라 타입이 정해지게 됩니다.

 

그리고 클래스를 템플릿 클래스로 만들어줄때의 방법을 설명 드릴게요.

우선 헤더파일부터 만들어 볼게요 클래스 추가로 클래스 이름 = Template 하고 기타옵션에 인라인을 체크하면

cpp는 생성 안 되고 헤더 파일만 생성되게 됩니다 헤더파일명도 Template로 하겠습니다.

생성을 한 뒤

#pragma once

// 클래스를 템플릿 클래스로 만들어주게 되면 .h 에 구현부분까지 모두 함께 만들어주어야 한다.
template <typename T>
class CTemplate
{
public:
    CTemplate()
    {

        // typeid(T).name()은 타입 명을 알아주는 코드이다
        std::cout << typeid(T).name() << std::endl;
    }

    ~CTemplate()
    {
    }

private:
    T       m_T1;
    T       m_T2;

}

(전처리기 생략)

int main()

{

    CTemplate<int> temp;

 

    return 0;

}

출력하면

int 가 출력이 된다 < > 안에 int를 넣었기 때문에 타입명인 int가 출력이 되는것이다

 

템플릿 특수화

템플릿 특수화 : 템플릿은 다양한 타입으로 변환되어 들어올 수 있습니다.

다양한 타입중 본인이 원하는 특정 타입만 함수 자체를 새로 구현할 수 있는 기능을 제공하는데

그것을 템플릿 특수화라고 한다.

ex)

template <typename T>

T Add(T Number1, T Number2)

{

    return Number1 + Number2;

}

// float타입

template <>

float Add (float Number1, float Number2)

{

    return Number1 + Number2;

}

 

template <>

double Add (double Number1, double Number2)

{

    return Number1 + Number2;

}

 

여기서 템플릿 특수화를 할때

template<>를 안 적으면 특수화가 아니라 독단적인 함수가 생성되는 것이다.

반응형

댓글