가상함수 말고도 virtual 키워드를 붙여줘야 할 대상이 하나 더 있다. 그건 바로 "소멸자" 이다. 즉, virtual 선언은 소멸자에도 올 수 있다. 


#include <iostream>

#include <cstring>

using namespace std;


class First

{

private:

char* name;

public:

First(char* name)

{

this->name = new char[strlen(name)+1];

}

~First()

{

cout<<"~First()"<<endl;

delete []name;

}

};


class Second :public First

{

private:

char* name;

public:

Second(char* fName, char* sName)

:First(fName)

{

name = new char[strlen(sName)+1];

}

~Second()

{

cout<<"~Second()"<<endl;

delete []name;

}

};


class Third :public Second

{

private:

char* name;

public:

Third(char* fName, char* sName, char* tName)

:Second(fName, sName)

{

name = new char[strlen(tName)+1];

}

~Third()

{

cout<<"~Third()"<<endl;

delete []name;

}

};


int main()

{

First* f1 = new Third("aaa","bbb","ccc");

delete f1;


return 0;

}



delete f1;     => 이 경우 First 클래스의 소멸자와 Second, Third 클래스의 소멸자가 동시에 호출되어야 한다. 하지만 그렇지 않다. 


실행결과에서 보이듯, 객체의 소멸을 First형 포인터로 명령하니 First 클래스의 소멸자만 호출되었다.

따라서 이러한 경우에는 "메모리의 누수(leak)" 가 발생하게 된다. 

그러니 객체의 소멸과정에서는 delete 연산자에 사용된 포인터 변수의 자료형에 상관없이 모든 소멸자가 호출되어야 한다. 

그리고 이를 위해서는 다음과 같이 소멸자에 virtual 선언을 추가하면 된다.


 #include <iostream>

#include <cstring>

using namespace std;


class First

{

private:

char* name;

public:

First(char* name)

{

this->name = new char[strlen(name)+1];

}

virtual ~First()

{

cout<<"~First()"<<endl;

delete []name;

}

};


class Second :public First

{

private:

char* name;

public:

Second(char* fName, char* sName)

:First(fName)

{

name = new char[strlen(sName)+1];

}

virtual ~Second()

{

cout<<"~Second()"<<endl;

delete []name;

}

};


class Third :public Second

{

private:

char* name;

public:

Third(char* fName, char* sName, char* tName)

:Second(fName, sName)

{

name = new char[strlen(tName)+1];

}

virtual ~Third()

{

cout<<"~Third()"<<endl;

delete []name;

}

};


int main()

{

First* f1 = new Third("aaa","bbb","ccc");

delete f1;


return 0;

}



가상함수와 마찬가지로 소멸자도 상속의 계층구조상 맨 위에 존재하는 기초 클래스의 소멸자만 virtual로 선언하면, 이를 상속하는 유도 클래스의 소멸자들도 모두 "가상 소멸자" 로 선언이 된다. 

그리고 가상 소멸자가 호출되면, 상속의 계층구조상 맨 아래에 존재하는 유도 클래스의 소멸자가 대신 호출되면서, 기초 클래스의 소멸자가 순차적으로 호출된다. 

Posted by scii
: