반응형

잠깐 알아가보기 전에 잡설을 해보겠다....

보고싶은 분은 접은글을 봐주시길....★

더보기

불과 몇달 전에 한 프로젝트 중에 이런 난잡한 코드를 썼다.

 

void InGameHumanBox::Update()
{
	if (human)
	{
		if (Utillity.CheckBaseClass<TutorialHuman>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV();
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Woman01>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV();
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Woman01>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV();
			m_gauge->index = ((int)human->GetHorrorScore()/10) + 25;
		}
		if (Utillity.CheckBaseClass<Woman02>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV() + 8;
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Woman03>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV() + 16;
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Man01>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV() + 4;
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Man02>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV() + 12;
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
		if (Utillity.CheckBaseClass<Man03>(human))
		{
			m_name->SetText(human->gameObject->GetName());
			m_profile->index = (int)human->GetHorrorLV() + 20;
			m_gauge->index = ((int)human->GetHorrorScore() / 10) + 25;
		}
	}
}

 

CheckBaseClass()가 무슨 메소드냐면....

대상이 P클래스를 상속받았으면 true를 반환

그렇다 그냥 인자로 받은 human친구가 템플릿 인자로 받은 클래스를 상속받았으면 true를 반환해주는 클래스다.

하지만 이런 삽질을 간단하게 만들어주는 편한 메소드를 찾아냈다...!

is_base_of 클래스 | Microsoft Learn

 

is_base_of 클래스

자세한 정보: is_base_of 클래스

learn.microsoft.com

오늘은 이 클래스에 대해 소개해보겠슴덩

template <class Base, class Derived>
struct is_base_of;

말그대로 Derived클래스가 Base클래스를 상속받은건지 알려주는 클래스인데요?

이걸로 편하게 상속받은 클래스를 확인해보시죠 ㅇㅅㅇ


근데 이렇게만 쓰면 섭섭하죠?

특정 객체와 클래스를 인자로 넘겨주면 해당 클래스를 상속받은건지 확인해주는 메소드를 작성해보겠습니다.

#include "pch.h"
#include <type_traits>

struct Human{};
struct Human01 : public Human{};
struct Human02 : public Human{};
struct Human03 : public Human{};

// P클래스를 상속받은 클래스면 true를 반환한다.
template <typename P, typename C>
bool CheckBaseClass(C _dest) {
    return std::is_base_of<P, C>::value;
}

int main()
{
    Human   _human;
    Human01 _human01;
    Human02 _human02;
    Human03 _human03;
    std::cout << std::boolalpha;
    std::cout << "human01 is base of Human : " << CheckBaseClass<Human>(_human01) << '\n';
    std::cout << "human02 is base of Human : " << CheckBaseClass<Human>(_human02) << '\n';
    std::cout << "human03 is base of Human : " << CheckBaseClass<Human>(_human03) << '\n';
    std::cout << "=================================" << '\n';
    std::cout << "human01 is base of Human01 : " << CheckBaseClass<Human01>(_human01) << '\n';
    std::cout << "human02 is base of Human01 : " << CheckBaseClass<Human01>(_human02) << '\n';
    std::cout << "human03 is base of Human01 : " << CheckBaseClass<Human01>(_human03) << '\n';

    return (0);
}

출력결과

human01 is base of Human : true
human02 is base of Human : true
human03 is base of Human : true
=================================
human01 is base of Human01 : true
human02 is base of Human01 : false
human03 is base of Human01 : false

그럼 여기서 궁금한 점 하나...

dynamic_cast와 is_base_of 와 성능차이는 얼마나 날까요? 성능차이가 나지 않으면 굳이 쓸 이유가 없는 코드죠?

그래서 코드로 확인을 해봤습니다...

더보기
#include "pch.h"
#include <iostream>
#include <type_traits>
#include <chrono>

struct Human {};
struct Human01 : public Human {};
struct Human02 : public Human {};
struct Human03 : public Human {};

template <typename P, typename C>
bool CheckBaseClass(C* _dest) {
    return std::is_base_of<P, C>::value;
}

template <typename P, typename C>
bool CheckDynamicCast(C* _dest) {
    P* temp = dynamic_cast<P*>(_dest);
    return temp != nullptr;
}

int main()
{
    Human01* _human01 = new Human01();
    Human02* _human02 = new Human02();
    Human03* _human03 = new Human03();

    const int iterations = 100000000;  // 반복 횟수 설정

    // std::is_base_of 시간 측정
    auto startIsBaseOf = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        CheckBaseClass<Human>(_human01);
    }
    auto endIsBaseOf = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsedIsBaseOf = endIsBaseOf - startIsBaseOf;
    std::cout << "std::is_base_of time: " << elapsedIsBaseOf.count() << " seconds\n";

    // dynamic_cast 시간 측정
    auto startDynamicCast = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        CheckDynamicCast<Human>(_human01);
    }
    auto endDynamicCast = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsedDynamicCast = endDynamicCast - startDynamicCast;
    std::cout << "dynamic_cast time: " << elapsedDynamicCast.count() << " seconds\n";

    delete _human01;
    delete _human02;
    delete _human03;

    return 0;
}

결과 (4번 시행)

1트
2트
3트
4트

2트때 차이가 너무 안나서 엥? 했다가 여러번 해보니까 나름 격차가 좀 있네요 ㅇㅅㅇ


그래서 어따씀?

에 대한 의문이면 게임엔진으로 따져보면 AddComponent같은 곳에 쓰지 않을까요?

 

오늘도 개꿀팁(?)을 알려드렸는데요?

이상으로 글을 마쳐보겠습니다. 감사합니다?

 

반응형

+ Recent posts