클래스 A를 상속받은 B.
A의 함수명을 바꾸고 싶다.
내가 원하는 함수의 이름으로 된 함수포인터로 함수명을 바꾼 것처럼 할 수 있지 않을까?
그냥 함수포인터로 쓰면 되겠지하고...
template <typename T>
class Container
{
public:
virtual T* Push() { //... }
protected:
//....
};
class Object
{
public:
//...
};
class ObjectContainer
:public Container<Object>
{
public:
typedef Object* (Container::*Push)();
Push PushObject = &Container::Push;
};
int main()
{
ObjectContainer obj_container;
obj_container.PushOjbect();
}
이러면 쓸 수 있을 것같았는데..에러 2개가 뜨더라
오류(활성) E0109 명백한 호출의 괄호 앞에 오는 식에는 함수 (포인터) 형식이 있어야 합니다.
오류 C2064 항은 0개의 인수를 받아들이는 함수로 계산되지 않습니다.
에러코드를 검색해보니..
항은 N개의 인수를 받아들이는 함수로 계산되지 않습니다.
식을 통해 함수가 호출됩니다. 식은 지정된 수의 인수를 사용하는 함수에 대한 포인터로 계산되지 않습니다.
라는데...흐음..?? 뭔 소린지 모르겠네ㅎㅎㅎㅎ??
예제코드를 보니..
int i, j;
char* p;
void func() {
j = i(); // C2064, i is not a function
p(); // C2064, p doesn't point to a function
}
아..결국 함수포인터를 잘못되게 대입했다는 뜻인가? 다른 예제를 보자.
// C2064b.cpp
struct C {
void func1(){}
void func2(){}
};
typedef void (C::*pFunc)();
int main() {
C c;
pFunc funcArray[2] = {&C::func1, &C::func2};
(funcArray[0])(); // C2064
(c.*funcArray[0])(); // OK - function called in instance context
}
...?? 뭐지? 이 코드는? 어째서 (c.*funcArray[0])()로 호출해야하는거지?? MSDN에선 더이상의 설명이 없네. 찾아봐야겠다.
결과적으로 좀 충격적이었다. 함수의 주소에 관한 문제였는데, 이걸 신경쓴 적이 없었다. 이런걸 가르쳐주시는 분들은 대체 어디서 배우시는거지??
32비트 시스템에서 일반 함수와 클래스의 정적 멤버 함수는 4바이트 포인터 값 하나로 표현가능하다. 그래서 함수 포인터가 동작가능한거고.
하지만, 클래스의 비정적 멤버 함수의 경우에는 '오브젝트의 주소 + 비정적 멤버 함수 주소' 형태로 되어있다. 비정적 멤버 함수 내부에서 클래스 멤버 변수를 참조하는 코드는 항상 오브젝트의 주소를 알고 있어야하기 때문이다.
따라서 (funcArray[0])()과 같은 코드는 컴파일러가 C::func1 멤버함수를 호출하기 위해 클래스의 주소와 멤버 함수의 주솔르 모두 알고 있어야 호출이 가능하다.
예를들어, NAMESPACE::func1같은 호출은 컴파일러가 단순히 네임스페이스의 func1 함수 주소만 알고있어도 호출가능하다. 따라서 ANSI C++에서는 비정적 멤버 함수의 주솔르 포인터 변수에 저장할 수 없다. 32비트 시스템에서 오브젝트 주소 + 함수 주소의 8바이트 값을 4바이트 포인터 변수에 넣을 수가 없기 떄문이다.
라는 이유다...결국 클래스 멤버 함수는 '클래스의 주소 + 멤버 함수 주소'로 되어있기에 함수 포인터에 클래스의 주소가 같이 명시가 되어야한다는 이유였다...
심지어 나의 경우에는 템플릿까지 가미되어서 호출시킬려면
(obj_container.*(obj_container->PushOjbect))();
같은 해괴한 코드로 호출해야한다는거다... 다른 방법이 없을까하다가 방법을 찾은게 static_cast이다.
결론적으로 말하자면, 안된다... '비정적이 문제라면, 정적으로 바꾸면 되는거 아닌가?' 라는 단순한 발상에서 시작되어서 'static_cast가 있었는데..그거 비정적으로 정적으로 바꿔주는 형변환이지 않을까?' 라는 미친 생각을 함. 지금 생각하면 어떻게 비정적을 정적으로 형변환을 한다는건지.. 여튼 static_cast는 암시적 형변환에서 검사를 하는 것이지. 정적으로 바꿔주는 형변환이 아니다. 애초에 정적 메모리에 일시적으로 올린다는게 말이 안된다. 힙 메모리도 아니고...
정말 답이 없는 것인가?
함수 포인터로 함수명 변경하기 (완결) (0) | 2018.04.24 |
---|---|
Epoll (0) | 2018.03.22 |
declspec에 대해 (0) | 2018.02.23 |
RAII (1) (0) | 2018.01.28 |
VS Code로 C++ 디버깅 (0) | 2018.01.25 |
댓글,
Lowpoly
게임 서버 프로그래머 지망생