2017-01-09 15 views
0

런타임시 메소드가 순수 가상인지 확인하는 방법이 있습니까? 사실, 파생 클래스의 소멸자가 이미 실행되었지만 여전히 기본 클래스가 살아 있는지 알 수있는 방법이 있는지 의문입니다. 메소드가 순수 가상인지 확인하십시오 (C++)

은 (간체) 제 경우입니다. 런타임 오류 A "라는 순수 가상 함수가"매우 산발적으로 (~ BaseClass로 실행되는 동안 해봐요가 호출 될 때 발생

class BaseClass{ 
private: 
    class ThreadUtil *threadUtil; 
public: 
    Mutex mutex; 
    ~BaseClass(){ 
       threadUtil->Terminate(); 
       MutexLocker ml(mutex); // Avoid destruction during use 
    } 

    virtual Size size()=0; 
}; 

class Derived:public BaseClass{ 
public: 
    Size size()override{return Size(100,80);} 
}; 


class ThreadUtil{ 
private: 
    bool terminate; 
    BaseClass *owner; 

public: 
    void Run(){ 
     while(!terminate){ 
      if (!IS_OWNER_SIZE_FN_PURE_THAT_S_THE_QUESTION){ 
       MutexLocker ml(owner->mutex); 
       DoSomething(owner->size()); // Runtime error if in the dtor of BaseClass 
      } 
     } 
    } 
}; 

스레드를 종료 + 파생 클래스의 잠금은 안전하지만 BaseClass에서 수행하고 싶습니다 (특히 파생 클래스가 많은 경우).

이것을 구현할 수있는 이동성이 뛰어나고 (플래그가없는) 방법이 있습니까? .. 또는 위의 d가 잘못되었습니다. esign?

편집 : -------------------- 일부로서

가 언급 한은 순수 가상 실제 문제가되지 않습니다. 스레드가 여전히 실행중인 기본 클래스의 소멸자로 들어갑니다.

  • 만들기 : 실제 질문은 어쩌면 "? 는 기본 클래스에서 미리 소멸자 메소드가 할 수있는 방법이"해야 제레미 Friesner 가리키는 Is there any automated way to implement post-constructor and pre-destructor virtual method calls?에서

    , 흥미로운 생각이있다 기본 클래스의 소멸자 및 파생 클래스가 보호되므로 삭제할 수 없습니다.

  • BaseClass의 소멸자를 가상으로 만들기. 먼저 스레드를 종료하는) (삭제하고 기본 클래스에 구현
  • 는 (있는 가상 파생 소멸자가 호출) 소멸자 당신은 여기 잘못 짚었하고
+1

왜 기본 클래스 소멸자가 가상이 아닙니까? –

+2

순수한 것뿐만 아니라 dtor에서 가상 기능을 호출하고 싶지는 않습니다. 보통 –

+4

순수 가상은 여기에서 빨간색 청어입니다. 진짜 문제는'Run'은 더 이상 존재하지 않을 때 객체에 접근하려고 시도한다는 것입니다. 해결책은 소유권을 적절히 관리하는 것입니다 (예 : 원시 포인터 대신'std :: shared_ptr/weak_ptr'을 사용한다. –

답변

7

호출 - 올바른 C에서 + +를 프로그램에서는 순수 가상 함수를 호출하는 것이 불가능합니다 (호출하려고하면 컴파일러에서 오류로 표시되기 때문에) 런타임에 함수가 순수 가상 함수인지 여부를 결정할 필요가 없습니다.

때때로 "순수 가상 함수 호출 됨"오류가 발생하는 이유는 프로그램이 버그가 있기 때문입니다. 특히 Run() 메서드가 해당 개체에서 메서드를 호출하는 경쟁 조건으로 인해 고통을 겪고 있습니다. 파괴되는 과정에서.

여기에서해야 할 일은 스레드가 종료되었는지 확인하고 (종료 할 스레드를 요청한 다음 pthread_join() (또는 이와 비슷한 다른 API를 호출하여 스레드가 100 개가 될 때까지 차단합니다. %이. 만 후 정리 을 시작 실행하는 동안 스레드가 액세스 할 수있는 모든 물체를 파괴 전에) 멀리 사라 스레드 죽은, 그리고 그런 식으로 당신은 따라서 경쟁 조건 및 오류/충돌.

을 피할 것

BaseClass 소멸자 함수에서 pthread_join() 호출을 배치 할 수 없다는 점에 유의하십시오. 왜냐하면 BaseClass 소멸자 함수가 실행될 때까지 객체의 하위 클래스 레이어가 이미 있으므로 파괴되었습니다. 을 정리하여의 BaseClass가 수퍼 클래스 인 객체를 삭제하기 전에 정리해야합니다.(부여는 AFAICT 이후 발신자가 수동으로 미리 삭제 스레드 종료 함수를 호출 확인해야, C++에서 그 순서를 자동화하기 위해 조금 어색한, 특히 no easy/automatic/transparent way to automate the generation of the pre-destructor thread-shutdown code있다)

+1

예, 순수 가상은 실제 문제가 아닙니다. 스레드가 여전히 실행중인 기본 클래스의 소멸자로 들어갑니다. 실제 질문은 "기본 클래스에 predestructor 메서드가있는 방법이 있습니까?" 베이스의 소멸자 만들기 및 파생 클래스 개인 그래서 호출 할 수 없습니다 삭제 - - 소멸자가 가상 ​​만들기 : 링크에서 는 재미있는 아이디어가있다. - 스레드를 먼저 종료하고 소멸자를 호출하는 기본 클래스 인 Delete()를 구현합니다 (파생 된 소멸자가 호출 됨) – Joan

0

휴대용 깨끗한 있는가 (플래그 없음)이 방법을 구현하는 방법은 무엇입니까? ... 또는 위의 디자인에 무엇이 잘못 되었나요?

스레드가 종료되기 전에 개체가 파괴되는 것을 방지하고 휴대용 방식으로 정리할 수 있습니다. TheradUtil 클래스는 적절한 유형의 스마트 포인터를 통해 BaseClass에 소유권을 소유하거나 공유 할 수 있습니다.