2016-07-25 65 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”和“强盗”。

我该怎么做?我期望我的代码按原样工作,因为“Thug”函数不是虚拟的,所以Thug *指针调用Thug函数时不应该调用任何东西?

为什么我的代码不能按照我的意图工作?我的困惑在哪里?

什么是简单的方法来获得我的预期行为?

+0

我很困惑。你已经创建了两个'Tupac'实例 - 你为什么期望它们的行为不同?虚拟成员函数的重点是调用派生最多的类中的重写。 –

+0

另外,'delete tupac;'和另外两个'delete'调用表现出未定义的行为,因为'Criminal'的析构函数是非虚拟的。 –

+1

*“这个”Thug“函数不是虚拟的”* False。虚拟函数的覆盖本身是虚拟的,尽管虚拟关键字可以省略。 'Thug :: getType()'和'Thug :: getCrime()'实际上是虚拟成员函数。 –

回答

4

virtual成员函数的性质是继承的。您可能没有声明Thug::getType()virtual,但它仍然是因为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

对,不会删除tupac调用Criminal析构函数,然后释放分配给tupac的内存? – Jason

+0

@Jason这会叫'刑事'析构者,是的。但它不会称为“Thug”或​​“Tupac”析构函数。 – Barry

+0

@Jason no,析构函数不是虚拟的,所以当你删除一个犯罪指针时,它会调用犯罪析构函数。 – kfsone