요즘 C++의 virtual 메카니즘에 빠져서 산다. virtual.. 그리 오랜시간 보아왔는데도, 여전히 어렵다.. 다음은 오늘 알아낸 것들.

1. RTTI(Run-Time Type Identification), 실행 중에 기반(base) 클래스 타입 포인터의 실체를 밝혀내는데 쓰이는 typeid 연산자. 그 기반 타입의 포인터가 다형성을 지닌 클래스(polymophic class), 즉 "virtual 함수가 있는 클래스"가 아니면 아무짝에도 쓸모가 없다. "typeid(기반 타입의 포인터)" 해보았자, 보이는 그대로 그 기반 타입임만을 알려줄 뿐, 실제 담겨있는 타입, 즉 그 기반 타입의 포인터로부터 파생된 타입(derived type)에 대해서는 알려주는 바가 없다.

2. dynamic_cast 연산자는 반드시 polymophic class에 사용해야 한다. polymophic class가 아닌 클래스에 사용할 경우에는 컴파일 오류(Visual C++의 경우, C2683 컴파일 오류 - dynamic_cast : 'type' is not a polymorphic type.)를 낸다. (이 때는 static_cast로 대체하여 사용하면 되더라..)

3. 기반 클래스 타입의 포인터로 자식 클래스 객체를 delete 연산자로써 소멸시킬 경우, 역시나 기반 클래스가 polymophic class가 아니면 기반 클래스 부위만 소멸될 뿐, 파생 클래스 부위는 소멸되지 않는다.

다음은 예제 코드다.
#include <typeinfo>
#include <iostream>

using namespace std;

class base
{
public:
    base() { cout << "base contructed." << endl; }
    virtual ~base() { cout << "base destructed." << endl; }
};

class derived : public base
{
public:
    derived() { cout << "derived contructed." << endl; }
    ~derived() { cout << "derived destructed." << endl; }
};

int main()
{
    derived* pD = new derived;

    base* pB = pD;
    derived* pD1 = dynamic_cast<derived*>(pB);

    if( typeid(*pB) == typeid(derived) )
        cout << "OK!" << endl;
    else
        cout << "No!" << endl;

    delete pB;
}
출력 결과:

base constructed.
derived constructed.
OK!
derived destructed.

base destructed.

위 예제 코드 중, base 클래스의 소멸자에 virtual이 없다면,

1. dynamic_cast가 담긴 문장에서 c2683 컴파일 오류가 난다.

2. 위 dynamic_cast가 담긴 문장을 제거한다고 해도,
   출력 결과는 "OK!"가 아닌 "No!"이며,

3. 마지막 delete 연산에서는 생성된 derived 객체의 base 부위만이 소멸되고
   derived만의 고유 부위는 그대로 남아, memory leak이 발생한다.
base 클래스의 소멸자에 virtual 키워드를 제거하고,
dynamic_cast가 담긴 문장을 주석 처리했을 경우의 출력 결과:

base constructed.
derived constructed.
No!
base destructed.
신고
Posted by 어쨌건간에
TAG , ,