2016-07-25 2 views
-1
#include <iostream> 
using namespace std; 

class Criminal { 
public: 
    virtual void getType() = 0; 
    virtual void getCrime() { cout << "Unknown" << endl; } 
}; 

class Thug : public Criminal { 
public: 
    void getType() { cout << "Thugging" << endl; } 
    void getCrime() { cout << "Gangsterism" << endl; } 
}; 

class Tupac : public Thug { 
public: 
    void getType() { cout << "Rapper" << endl; } 
    void getCrime() { 
     cout << "Being the best rapper to ever live" << endl; 
    } 
}; 

int main() { 
    Criminal* tupac = new Tupac(); 
    Criminal* thug = new Thug(); 
    Thug* poser = new Tupac(); // Thug has no virtual function 
    //Criminal shouldNotCompile; 

    tupac->getType();  
    tupac->getCrime();  

    thug->getType();   
    thug->getCrime();  

    poser->getType();  // I intend to call Thug::getType() 
    poser->getCrime();  // I intend to call Thug::getCrime() 

    delete tupac; 
    delete thug; 
    delete poser; 

    getchar(); 

    return 0; 
} 

출력은기본 포인터의 C++ 가상 클래스?

Rapper 
Being the best rapper to ever live 
Thugging 
Gangsterism 
Rapper 
Being the best rapper to ever live 

이다 그러나 나는 "Thugging"를 인쇄 할 수 깡패 포인터의 젠체하는 전화를 의도 "Gangsterism을."

어떻게하면됩니까? "Thug"함수가 가상이 아니기 때문에 내 코드가 그대로 작동 할 것으로 예상했기 때문에 Thug * 포인터가 Thug 함수를 호출하면 안되는 것이 무엇입니까?

왜 내 코드는 내가 그것을 의도 한대로 작동하지 않는 이유는 무엇입니까? 내 혼란이 어디 있니?

내 의도 된 동작을 얻을 수있는 가장 쉬운 방법은 무엇입니까? 멤버 함수

+0

혼란스러워. 당신은'투팍 (Tupac) '의 두 인스턴스를 만들었습니다 - 당신은 그들이 왜 다르게 행동 할 것이라고 기대합니까? 가상 멤버 함수의 전체적인 포인트는 가장 많이 파생 된 클래스의 재정의가 호출된다는 것입니다. –

+0

또한'delete tupac;'과 다른 두 개의'delete' 호출은'Criminal'의 소멸자가 가상이 아니기 때문에 정의되지 않은 행동을 보입니다. –

+1

* "The Thug"함수는 가상이 아닙니다. * False. 가상 함수의 재정의 (override)는 그 자체로 가상이지만,'virtual' 키워드는 생략 가능합니다. 'Thug :: getType()'과'Thug :: getCrime()'은 사실 가상 멤버 함수입니다. –

답변

4

virtual -ness 상속된다. 당신은 virtualThug::getType()을 선언하지 않을 수 있습니다,하지만 Criminal::getType()이기 때문에 여전히입니다. 그 객체 상속 Criminal에서 여전히 가상 파견을 통해 이동합니다 모든 유형에 getType() 호출. 명시 적 를 지정하지 않으면getType() 당신이 원하는 :

poser->getType(); // virtual dispatch, ends up invoking Tupac::getType() 
poser->Thug::getType(); // explicitly call Thug::getType(), no dispatch 

이러한 호출 :

delete tupac; 
delete thug; 
delete poser; 

이로 인해 Criminal의 소멸자 virtual을없는 위험하다. 실제로 모든 기억을 풀거나 모든 구성원을 파괴하지는 않습니다.

+0

맞아, 투팍을 삭제할 의향이 없으면 범죄 소멸자를 부른 다음 투팍을 위해 할당 된 메모리를 해제 할 수 있습니까? – Jason

+0

@ Jason'Criminal' 소멸자라고 부릅니다. 그렇습니다. 그러나'Thug' 또는'Tupac' 소멸자를 부르지 않을 것입니다. – Barry

+0

@Jason no, 소멸자는 가상이 아니므로 범죄 * 포인터를 삭제하면 범죄 소멸자가 호출됩니다. – kfsone