2014-07-25 175 views
3

在此示例中,我创建基础对象sphere(2),并将其地址分配给具有类型转换的派生类指针。然后我可以调用基础对象sphere(2)中不存在的fun()函数。我认为这很奇怪,因为Sphere中根本没有fun()的定义。但我可以进行类型转换并调用它。有人可以解释吗? 在此先感谢。从基类中不存在的基类中调用派生的方法

PS:输出是 “哈哈,我半径2球”

//---------sphere.h-------------- 
#ifndef SPHERE_H 
#define SPHERE_H 

class Sphere{ 
    private: 
     double _radius; 
    public: 
     Sphere(double radius){ 
      _radius = radius; 
     } 
     double getRadius(){ 
      return _radius; 
     } 
}; 

#endif 
//-----------ball.h-------------- 
#ifndef BALL_H 
#define BALL_H 

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

using namespace std; 

class Ball : public Sphere 
{ 
    private: 
     string _ballName; 
    public: 
     Ball(double radius, string ballName): Sphere(radius){ 
      _ballName = ballName; 
     } 

     string getName(){ 
      return _ballName; 
     } 

     void fun(){ 
      cout << "Haha I am a ball with radius " << getRadius() << endl; 
     } 
     void displayInfo(){ 
      cout << "Name of ball: " << getName() 
         << " radius of ball: " << getRadius() << endl; 
     } 
}; 

#endif 
//-------main.cpp---------------- 
#include "Ball.h" 
#include "Sphere.h" 

int main(){ 
    Ball *ballPtr; 
    Sphere sphere(2); 

    ballPtr = (Ball *)&sphere; 
    ballPtr -> fun(); 

    return 0; 
} 
+2

是不是未定义的行为很好? – user657267

+0

您可以使用C++ cast而不是c-cast。这里'dynamic_cast','ballPtr'将是'nullptr'。 – Jarod42

+0

@ Jarod42这里使用'dynamic_cast'会导致编译时错误,因为'Sphere'不是多态的。 – user657267

回答

3

那是单纯的 “运气”。您正在调用对象上的某个函数,同时假装它是另一种类型(BallSphere,但并非全部Sphere都是Balls,而且这肯定不是)。这是未定义的行为,可以做任何事情,包括敬酒你的猫。小心。

+1

UB的死亡,最糟糕的途径之一... – SirGuy

1

该函数不是虚拟的,所以它只是被您强制指定的对象指针的类型调用Ball *。 '球'类直接和非虚拟地从'球体'继承,并且没有额外的基类,所以 - 幸运的是你! - Sphere::radius成员相对于球的*this的位置在getRadius()中正确,并且您会得到正确的输出。

相关问题