C++ 추상 클래스와 포인터 캐스팅, 다중상속 ㅅㅂㄹㅁ

프로그래밍 2007.06.13 22:41
상황설명

A라는 부모 클래스를 만들고, 이 A라는 클래스의 포인터인 A* pA 를 인자로 하는 foo(A* pA)를 정의해서 사용중이었다. 이 함수의 인자로는 A를 상속한 B나 C클래스를 예상할 수 있으며, 이 B와 C클래스는 I라는 순수 가상함수를 상속한 다중상속 객체들이었다. I는 순수가상함수인 Vfoo()를 가지고 있었다. C는 생성자에서 A의 함수(가상함수가 아니다)를 호출한다.

사용자 삽입 이미지

이런 상속관계 (수정)


vector<I*> vt;

...

C* pC = new C;
I* pI = (I*)pC; // C* -> I*
vt.push_back(pI);

...

A* pA = (A*)vt[0]; // C* -> I* -> A*
foo(pA);

...

foo(A* p_pA)
{
    I* pI = (I*)p_pA; // C* -> I* -> A* -> I*
    pI->Vfoo(); // 여기서 문제발생
}

문제발생

문제는 C형 인스턴스를 가리키는 A형 포인터 pA_dir_C를 foo(A* pA)의 인자로 넘겨주면서 일어났다. foo(A* pA)함수 내부에서는 인자로 받은 pA를 (I*)pA 로 형변환하여 Vfoo()를 호출하는 루틴이 들어있었는데, 여기서 에러가 발생한 것이다. (6025 pure virtual function call)

Watch를 통하여 살펴보니 vftable의 문제였는지, Vfoo()가 아닌 엉뚱한 함수가 불려오더라. (다른 추상 클래스 I2에서 오버라이딩 된 가상함수였다.) 포인터 형변환에서 가상함수 테이블에 변화가 오는 것일까?

해결책

결국 C* -> I* -> A* -> I* 와 같은 여러 번의 형변환을 거치지 않고 C* -> I* 상태에서 pI->Vfoo() 식으로 형변환 단계를 줄여서 사용하였다. 정확히 말하면 문제를 해결한 것이 아니라 회피한 것이나 마찬가지다. 하지만 적당한 레퍼런스도 없고, 도와줄만한 사람도 없고 해서. 코드 길이는 좀 길어질지 몰라도 저런 식으로 함수를 통하는 단계를 줄여버렸다.

감상

쩐의 전쟁이 너무 재밌다.


Trackbacks 1 : Comments 11

[기사] "내 꿈은 골방에 처박힌 프로그래머"

생각하다 2007.05.16 21:45
기사링크 : http://zine.media.daum.net/mega/h21/200705/15/hani21/v16737605.html

확실히 요즘 아이들(나도 여기에 반쯤은 포함된다 싶다)은 문제다. 사람과의 소통이 너무나도 단절되어 있다. 오죽하면 학원 때문에 죽겠네 뭐하네 하는 아이들이 친구들을 만나고 싶어 학원에 다니겠는가? (그조차도 피곤해서 잘 놀지도 못한다더라) 요즘들어 사이버공간에 대한 이슈, 뉴스를 많이 접하는 것 같다. 특히나 실생활(사생활, 사회)에 관련된 뉴스들.

뉴스를 접할 때마다- 어째서 사람들은 사이버 공간에 그렇게 큰 의미를 부여하려는 것인가, 싶다. 아니 실제로는 사람들이 왜 그렇게 생각하는 것인지가 궁금하다. 인터넷은 그저 매체인가? 전공자이기 때문에 그 관심은 더하다. 내가 볼 때 인터넷은 도구다. 싸이월드 역시 자기표현의 매체에 불과하다. 안락한 만남의 장이라는 것도 결국엔 일시적인 사람들간의 연결에 불과하지 않나? 본질은 사이버 공간이 아니다. 인간과 인간의 연결 그 자체라는 거다. 하지만 정말 인터넷이란 그 자체로 다른 공간인가?

실존하지 않는 사이버 공간을 다뤘던 옛 SF들이 생각나는 밤이다.



Trackbacks 0 : Comments 1