2010-08-12 2 views
1

개체의 가상 메서드 내에서 개체를 간접적으로 삭제할 수 있습니까? "정의 된 동작"(객체를 삭제 한 후에 아무 것도 액세스하지 않는 한)입니까?
예 :직접 가상 메서드에서 개체를 간접적으로 삭제합니다. 정의 된 행동입니까?

#include <memory> 
#include <stdio.h> 

using std::tr1::shared_ptr; 

struct Child{ 
    virtual void selfdestruct() = 0; 
    virtual ~Child(){ 
     fprintf(stderr, "child destroyed\n"); 

    } 
}; 

typedef shared_ptr<Child> ChildPtr; 

struct Parent{ 
    ChildPtr child; 
    void clear(){ 
     fprintf(stderr, "clear\n"); 
     child = ChildPtr(); 
    } 
    Parent(); 
}; 

struct DerivedChild: public Child{ 
    Parent* parent; 

    virtual void selfdestruct(){ 
     fprintf(stderr, "selfdestruct\n"); 
     if (parent) 
      parent->clear(); 
    } 

    DerivedChild(Parent* p) 
    :parent(p){ 
    } 
}; 

Parent::Parent(){ 
    child = ChildPtr(new DerivedChild(this)); 
} 


int main(int argc, char** argv){ 
    Parent p; 
    p.child->selfdestruct();  
    fprintf(stderr, "child is 0x%08x\n", p.child); 
    return 0; 
} 

출력 :

selfdestruct 
clear 
child destroyed 
child is 0x00000000 

이 정의 행동하지 않으면, 내가 대신 무엇을 할 수 있습니까?

답변

4

음, 가상 메서드는 delete this을 호출 할 수 있습니다. 호출 한 후에는 객체 인스턴스를 수행 할 수 있거나 정의되지 않은 동작을 호출 한 것 외에는 아무 것도 없습니다. 이는 다른 메소드 (심지어 가상 메소드가 아님) 호출, 인스턴스 변수 액세스 등을 포함합니다.

Child 개체에 가상 소멸자가 필요하기 때문에 위의 특정 코드는 정의되지 않은 동작을 호출합니다.

그러나 개체가 스스로를 파괴해야하는 모든 유형의 상황은 최상의 디자인이 아닙니다.

+0

"자식 개체에는 가상 소멸자가 필요합니다." 그것은 "오타"였습니다. 나는 그것을 가상으로 만들겠다고 맹세 할 수있었습니다. 그러나 개체가 스스로를 파괴해야하는 모든 유형의 상황은 설계의 최선이 아닙니다. " 제 경우에는 객체가 그것을 지우는 것을 유발할 수있는 상황이 있습니다. 그래서 내가 그 질문을했다. – SigTerm

+0

@SigTerm :'delete this'는 붉은 깃발이지만, 간접적으로 복잡한 절차가 끝나면 자신을 처분하는 것은 그리 좋지 않습니다. – Potatoswatter

1

개체 자체가 파괴 될 수 있습니다. 가상 메서드가 어떻게 바뀌는 지 나는 모르겠다.

1

기본적으로 대답은 delete this;입니다. 그렇기 때문에 대답은 '예'입니다.

void clear(){ 
    fprintf(stderr, "clear\n"); 
    child = ChildPtr(); 
} 
0
struct X{ 
    X() {f();} 
    virtual void f(){delete this;} 
}; 

int main(){ 
    //X x;  // evil, 'delete this' is an error, because 'new' itself was not done 
    //x.f();  

    X *p = new X; // Ok, but 'p' now points to an already deleted memory 
    p->f();  // evil, double delete 
} 

그래서, 자기 삭제, 항상 까다로운 문제입니다.

그러나 질문은 객체의 자체 파괴에 관한 것이지, 객체가 생성되는 메모리의 할당 해제가 필요하지는 않습니다.

는 IT 개체가 '새 위치'

struct X{ 
    X() {f();} 
    ~X(){} 
    virtual void f(){this->~X();} // here an object destroys itself, but no memory deallocation is done. This is fine and safe as well. 
}; 

int main(){ 
    char *p = new char [sizeof(X)]; // assume alignment requirements are met 
    X *px = new (p) X(); 
    delete [] p; 
} 
0

를 사용하여 메모리 위치에 구성되어 있는지 확인하십시오 경우에만이 안전이 완벽하게 유효하고 또한 일반적인 관행, 예를 들면이다 참조 카운팅을 구현하기 위해 (MS COM의 IUnknown 참조)

관련 문제