[c++] 개발 교양

이 내용은 절대적인 룰 이 아닌 권장사항이나 가급적 지켜짐이 좋다고 판단되는 부분을 다룹니다

포인터 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 로 선언해야 한다


댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다