2010-12-29 10 views
9
class B { 
virtual int foo(); 
}; 

class D : public B { 
virtual int foo() { cout<<"D\n"; } 
}; 

int B::foo() 
{ 
    /* how do i tell if this->foo() is overridden by a subclass, or if it will */ 
    /* simply recurse into B::foo()? */ 
    this->foo(); 
} 

main() 
{ 
D d; 
d.B::foo(); 
} 
+3

확실한 방법은 없을 것이다. 왜 그러고 싶니? –

+0

나는 일반인과 마찬가지로 dli.foo()에 전화하여 동의합니다. – Puppy

+1

개인적인 견해에 대한 답을 보충하고 싶습니다. 나는 왜 누군가가 무언가를하고 싶어하는지 결코 의심하지 않으려 고 최선을 다한다. 나는 그들이 왜 무언가를하고 싶은지를 알 수 없다. 나는 그들이 질문을했다는 것을 알고있다.나는 그들의 문제를 해결하고 해결할 대안을 제공하는 것이 좋다고 생각하지만, "보통 사람처럼"하는 말은 건설적이거나 도움이되지 않습니다. –

답변

8

답변 : 할 수 없습니다.

확장 할 항목이 있으면 확장 할 것입니다.

+0

그게 내가 생각한거야. – deltamind106

0

가장 안전한 방법은 foo()를 오버라이드하지 않고 프로그래머를 신뢰할 수없는 경우 기본 클래스에서 호출되는 OnFoo() 함수를 재정의 할 수있게하는 것입니다. MFC는 재발 방지로부터 보호하기보다는 기본 동작을 보장하기 위해이 작업을 많이합니다.

정적 레벨에서도 OnFoo()를 구현하는 모든 것이 '파일에서 찾기'로 쉽게 발견됩니다.

예. .. 나는 심지어이 제공 싫어

class B 
{ 
public: 
    B() 
    { 
     m_bInFoo=false; 
    } 

    int foo() 
    { 
     if(!m_bInFoo) 
     { 
      m_bInFoo=true; 

      int nRet = OnFoo(); 

      m_bInFoo=false; 

      return nRet; 
     } 

     return 0;// probably throw exception 
    } 

protected: 
    // inherited classes override OnFoo(), and never call OnFoo(); 
    virtual int OnFoo(){ return 0 }; 

private: 
    bool m_bInFoo; 
} 
1

(문법/컴파일하지 스레드 테스트되지 않음)하지만 여기 내가 작동하는지 증명하려면 편집

int B::foo() 
{ 
std::cout << "B" << std::endl; 
if (typeid (*this) != typeid(B)) 
    this->foo(); 
return 0; 
} 

입니다 MSVC++ 2010에서.

#include "stdafx.h" 
#include <iostream> 

class B { 
public: 
virtual int foo(); 
}; 

class D : public B { 
public: 
virtual int foo() { 
    std::cout<<"D\n"; return 0; 
} 
}; 

int B::foo() 
{ 
std::cout << "B" << std::endl; 

/* how do i tell if this->foo() is overridden by a subclass, or if it will */ 
/* simply recurse into B::foo()? */ 
if (typeid (*this) != typeid(B)) 
    this->foo(); 

return 0; 
} 


int main(int argc, _TCHAR* argv[]) 
{ 
D d; 
d.B::foo(); 

B b; 
b.foo(); 
return 0; 
} 

B 
D 
B 

증명 tput을 항상 여기에

변경 D를 작동하지 않습니다 그것은 더 이상

class D : public B { }; 
+0

그건 작동하지 않습니다. foo()가 오버라이드되었는지 알려주지 않고 실제로 D 객체의 foo()를 호출 할 때 코드가 무한대로 재귀 될 것입니다. OP가 피하고 싶어하는 것. 실제로 foo()가 호출되는 B가 실제로 더 구체적 인 버전인지 아닌지 여부를 아는 데 도움이되지 않습니다. 바로 그 것입니다. 사람들이 대답의 유효성을 확인하기 전에 손을 건들지 않았다면 더 의미가 있습니다. –

+0

@ Noah Roberts D가 B :: foo를 덮어 쓰지 않으면 재발합니다. 이는 스택 풀기를 사용하여 해결할 수도 있습니다. 같은 스택을 통해 B : foo()가 다시 입력되고 다른 변수를 만들려고 시도하면 B :: foo()를 입력 한 후 스레드 로컬 저장소에 플래그를 설정하는 변수를 만듭니다. 플래그가 설정되고 종료됩니다. 스택이 unwind되면 변수의 파기는 플래그를 해제 할 수 있습니다. 내 솔루션은 그가 겪었을 수있는 다른 시나리오를 읽지 않았으므로 그가 내린 정확한 문제를 해결합니다. –

2

한 가지 방법은 foo()순수 가상 함수를 만드는 것입니다 작동하지 않습니다B, 으로 정의하십시오. 그렇게하면 B의 파생 클래스는이어야하며 foo()을 정의해야합니다. 여기서 B,

class B 
{ 
public: 
     virtual int foo() = 0; //pure virtual function 
}; 

//pure virtual function also has a default implementation! 
int B::foo() 
{ 
     std::cout << "B" << std::endl; 
     this->foo(); //this will call the overridden foo() in the derived class! 
     return 0; 
} 

는 B의 파생 클래스는 foo는()를 구현하지 않는 경우에, 당신은 심지어 파생 클래스의 인스턴스를 만들 수 없습니다입니다!

는 ideone에서 전체 작업 코드를 참조하십시오 : 그런데 http://www.ideone.com/m8O2s

, 내 개인적인 의견 일 것, 클래스와 같은 디자인으로 시작하는 것이 나쁘다. 파생 클래스 foo()에서 B::foo()으로 전화하면 어떨까요? 재귀?

+0

이렇게하면 B의 인스턴스를 인스턴스화 할 수 없습니다. B 유형의 객체를 계속 만들고 싶은지 여부는 알 수 없습니다. –

+0

물론 주위에 엔지니어를 배치 할 수있는 방법이 많이 있지만 질문은 내가 원하는 것을하기 위해 C++ rtti에 내장 된 방법이 있는지입니다. – deltamind106

0

다른 사람들도 지적했듯이이를 수행 할 수있는 확실한 방법은 없습니다. 나는 당신이 당신의 디자인을 재고 할 것을 촉구한다 ...

+0

글쎄, 예, 이전 개발자의 어색한 코드를 재 설계 할 수 있다면 좋겠지 만, 슬픈 코드는 현재 카드에 없습니다. – deltamind106

관련 문제