WinAPI 56 Tool (4)

CJB_ny·2022년 10월 3일
0

WinAPI

목록 보기
58/79
post-thumbnail

오늘 배운거 👍👍👍

  • 상속받는 클래스의 멤버함수를 함수 포인터로 호출하는 방법

  • 멤버클래스를 호출할 때 및 바인딩할 때의 유의할점 ❗❗❗

    상속받는 클래스의 멤버 함수를 함수포인터로 바인딩을 할 때에 주의할 점이 전방선언으로 얼렁뚱땅 넘어갈 수 없고 정확한 클래스의 정보를 알야아 바인딩이 가능하다.

    이부분에서 시간 오래걸림.

  • 함수 포인터를 사용해서 함수 바인딩 하는 부분


전역함수 vs 멤버함수 참이점 ❗❗❗

현재 ToolScene의 Enter부분에서

이렇게 Clone한 UI에 대해서만 SetClickedCallBack함수를 통해서 ChangeSceneByBtn이라는 함수를 연결해주었다.

-> 이렇게되면은 클릭이벤트 발생시 해당함수를 호출 해주게되는데

지금 함수포인터를 받는 방식이

이러한 방식이라, 만약에 다른 함수를 연결해서 넣어주고 싶으면 함수 모양을 같이 맞추어야하고

또, ChangeSceneBtBtn함수와의 가장 큰 차이점은 이 함수는 전역함수라 언제든지 호출이 가능하지만

LoadTileData, SaveTileData와 같은 함수는 '멤버 함수'라는 가장 큰 차이점이 존재한다.

둘의 가장 큰 차이점은 ❗

전역함수는 그냥 막바로 사용할 수 있지만 멤버함수는 '객체'가 필요하다.

그렇다면은 SetClickedCallBack함수를 템플릿으로 만들어 두어도 멤버함수를 매핑해서 사용을 할려면은 객체의 이름을 명시해서 호출을 해야할 것이다.

그래서 멤버함수의 주소를 아무리 전달할 수 있다고해도 전달된 주소(멤버함수)를 호출할 수 있는 '객체'가 필요하다.

멤버함수 호출 ❗❗❗

이러한 형태를 가지는 전역함수 뿐만 아니라

Scene이 보유하고있는 또는 Scene을 상속받는 클래스의 멤버 함수를 호출하고싶다면은?


함수 포인터 정리글

https://velog.io/@starkshn/%ED%95%A8%EC%88%98-%ED%8F%AC%EC%9D%B8%ED%84%B0-1-2#typedef-%EC%9D%98-%EC%A7%84%EC%8B%A4


이런 typedef void(*BTN_TYPE) () 이러한 형태는 전역/정적 함수들만을 담을 수 있다.

그래서 특정 객체를 기반으로 호출하냐 안하냐가 가장 큰 차이점인데

멤버함수는??

특정 클래스의 멤버함수를 라는 것을 명시해주기 위해서

클래스이름:: 이런식으로 정의해주어야한다.

근데 어떤 클래스의 멤버함수인지를 명확하게 해주어야하기 때문에

요렇게 ㄱㄱ. 이게 바로 멤버함수 포인터 변수이다.

이게 무슨 뜻이냐하면은 함수 포인터를 받을 것인데, 아무거나 받지를 않을 것이고

오로지 ToolScene에 구현되어있는 멤버함수를 받는데, 반환타입이 void이고 인자로 아무것도 받지않는 시그니쳐를 가지는 멤버함수 이여야한다는 것이다.

이거만 있으면 동작하는 것은아니고 제대로 호출을 하려면은 '객체'도 필요하다.

문제점 ❗❗

이거 ToolScene::이런식으로 타입을 명확히 해주어야 하기 때문에

'범용성'이 없다.

그래도 그나마 다행인 부분이 ToolScene::*TOOL_SCENE 이런식이 아니라

부모 클래스 CScene::* 이런식으로 선언해주면 또 문제가 없기는 하다.

근데 이게 당연할 수도 있는게 ToolScene 객체는 어쨋든 자신 주소의 가장 첫번째 offset애 Scene의 주소를 담고 있으니까...

근데 근본적은 문제는 해결이 안됨. Object에 있는 멤버함수를 연결해주고 싶다면은??

설명 안할려고 했던 부분

원래라면은 사실 아무 공통점이 없어보여도, 라이브러리에 존재하는 모든 클래들을 최초의 부모 클래스로 묶어두는게 좋다.

이런식으로...

이렇게하면 SetClicked함수 연결해줄 때 부모클래스:: 이렇게해주면 어떤 클래스의 멤버 함수이든지 간에 다 받을 수 있는데 말이다.

그래서 일단 양보해서 Scene의 멤버 함수포인터만들 받을 수 있는 정도만 하고 넘어가도록 하자.

만약 오브젝트 타입 호출하고싶다면은

이렇게만 하나 더 선언하면은 된다.

그렇다면은 이제

이런식으로 ButtonUI클래스의 멤버함수들이 이런식으로 필요하다.

그리고 이런식으로 '오버라이딩'을 해주면은 된다.

객체로 함수 호출 부분 ❗❗❗

객체가 있다면은 이런식으로 호출을 할텐데

sceneInstance각 객체의 주소를 가지고있으니까 *로 접근을 하면 원본 말한다.

이렇게되면 멤버함수를 호출할 때 '.'으로 호출을 함.

pf_sceneFunc의 멤버함수를 호출을 하는데 pf_sceneFunc가 '함수 포인터'이기 때문에

이렇게 '*'를 붙여서 원형을 표시해주어야한다.

이렇게 호출 해주어야한다.

(모양 존나 못생기고 더럽다)

CallBack 테스트 ❗❗❗

현재 ToolScene의 Enter부분에서 buttonUI의 Clone이된 buttonUI 쉬프트키 대신에

자신을 클릭하였을 때 자기 자신의 멤버함수인 SaveTileData를 호출하게 하고싶은상황이다.

이렇게 연결해 줄 수 있다.

지금은 ToolScene의 SaveTileData라고 & 주소표시를 해주었는데

dynamic_cast<ButtonUI*>(ClonePanal->GetChild()[0])->SetClickedCallBack()

이안에서도 &ChangeSceneBtBtn, 0, 0 이런식으로 주소연산자를 붙여주는게 맞다.

전역함수는 암묵적으로 '&'를 안붙여도 함수의 이름을 주소라고 인식을 해주는데

멤버함수 포인터의 경우에는 붙이는게 정석이다.

그리고

이런식으로 캐스팅을 해준다. 캐스팅 부분을 빼주어도 되는데 명시적으로 캐스팅을 해주어야한다.

문제점

지금 이

두 함수 헤더에다가 구현을 해놓으니까 null값들어온다.

일단 .cpp로 옮기도록 하자.

옮기고 나서 -> 실행된다.

바로 예외발생함.

각각의 ButtonUI.h에서

이런식으로 전방선언을 하여 다 알려주고

거기에 맞는 함수오버라이딩도 다 진행해 주었지만 에러가 난다.

일단 헤더에서 헤더를 참조하는 부분은 최대한 지양하려고 했지만 이부분만 헤더를 참조를 해보도록 하자.

ButtonUI 부분에서'

'

그냥 이렇게 헤더를 참조를 하고 다시 실행을 하면은

CloneUI에 대해서만 함수포인터를 연결을 해주어서

버튼 클릭시 잘 뜬다.

아 그리고 헤더에서 참조했으니까

이부분 지워도 ㄱㅊ.

알아야할 점 ❗❗❗

멤버함수 포인터 선언을 할 때에는 정확한 클래스 정보를 알아야한다.

전방선언으로 얼렁뚱땅 넘어갈 수 없다.

클래스에 대한 멤버함수를 받겠다라고 해놓고

클래스에 대한 정보가 없으니까 바인딩 할 때 문제가 생기는 것이다.

그래서 어쩃든 Scene 타입으로 멤버함수를 받게한다면으 Scene을 상속받는 클래스의 멤버함수도 호출할 수 있다는 것을 알았다.

과제

UI에서 클릭을 하여서 해당 타일의 정보를 클릭했을 때 기억을 하고 있다가

현재 나의 화면은 타일에 아무 타일이나 클릭을 하면 UI에서 클릭한 텍스쳐 이미지가 타일에 입혀져서 변경이 가능하도록 만들어라.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글