이 내용은 절대적인 룰 이 아닌 권장사항이나 가급적 지켜짐이 좋다고 판단되는 부분을 다룹니다
포인터 delete 후 nullptr 대입
car* mycar = new car("avante"); delete mycar; mycar = nullptr; if (mycar != nullptr) mycar->drive();
포인터를 사용 할땐 항시 nullptr 상태 인지 체크 한다 이건 따로 기술할 의미도 없다
그때에 nullptr 인 상태를 체크 하기위해서는 포인터 변수는 항상 사용후 삭제시 쓰레기주소가 남아있지 않도록 nullptr (NULL,0 보다는 nullptr) 을 대입하자
하물며 함수 스코프 끝 이라 다시 그 변수에 접근할 수 없는 코드라 할지라도 이건 습관이자 약속이자 미래를 위한 한줄이다
소멸자는 virtual 로
class ClassName { ClassName(){ }; virtual ~ClassName(){ } }
가상함수가 아닌 소멸자는 하위 인스턴스를 가진 부모클래스 인터페이스 에서 호출되지 못한다
c++ 은 다형성 아래에서 virtual function table 을 가지며 virtual 함수가 있을때만 해당 vftable 이 생긴다 vftable 에 해당 함수가 있어야만 현재 포인터의 타입 이외에 어떤 함수들이 실제 접근할 수 있는지 (본 인스턴스) 알 수 있다
상속 예정이 없더라도 가급적 virtual 선언은 잊지 말자
처음엔 하지않으려 했지만 위 car 를 다른 클래스에서 상속이 하고싶어 질수도 있다
아래 샘플을 추가해 본다
#include <iostream> class parent { public: parent() { std::cout << "construct parent" << std::endl; } virtual ~parent() { std::cout << "destructor parent" << std::endl; } }; class child : public parent { public: child() :parent() { std::cout << "construct child" << std::endl; } ~child() { std::cout << "destructor child" << std::endl; } }; int main() { //child c1; parent* c1 = new child(); delete c1; }
이상태는 상위 클래스의 소멸자는 virtual 이다
이때에는 하위 소멸자가 정상적으로 호출된다
construct parent
construct child
destructor child
destructor parent
이때 디버깅을 통해 vftable 을 보자
vfptr 상에 destructor 가 존재함을 알 수 있다
소멸자가 virtual 이 아닌경우
construct parent
construct child
destructor parent
자식 클래스의 소멸자가 정상호출되지 못하며
vfptr 이 존재하지 않는 것을 알 수 있다
상속을 제한하고자 할 경우 소멸자를 final 로 선언해야 한다
댓글 남기기