【问题标题】:Inheritance polymorphism function call继承多态函数调用
【发布时间】:2017-04-29 16:22:08
【问题描述】:
class Shape 
{
   public:
      virtual void draw() const {cout<<"draw shape"<<endl;}
};



class Point : public Shape 
{
   public:
      Point( int a= 0, int b = 0 ) {x=a; y=b;}  // default constructor
      int getx() const {return x;}
      int gety() const {return y;}
      virtual void draw() const {cout<<"draw point("<<x<<","<<y<<")\n";}
   private:
      int x, y;   // x and y coordinates of Point
};


class Circle : public Point 
{
   public:  // default constructor
      Circle( double r = 0.0, int x = 0, int y = 0 ):Point(x,y) {radius=r;}
      virtual void draw() const 
      {cout<<"draw circle("<<getx()<<","<<gety()<<","<<radius<<")\n";}
   private:
      double radius;   // radius of Circle
};

void functionCall(Shape *arrayOfShapes[3])
{
    Shape shape;
    Point point( 7, 11 );            // create a Point
    Circle circle( 3.5, 22, 8 );     // create a Circle

    arrayOfShapes[0] = &shape;
    arrayOfShapes[1] = &point;
    arrayOfShapes[2] = &circle;

}

int main()
{


    Shape *arrayOfShapes[3];

    functionCall(arrayOfShapes);
    for(int i=0; i<3; ++i)
    arrayOfShapes[i]->draw();

    return 0;
}

当我尝试运行时,出现了分段错误。似乎主函数无法检索arrayOfShapes[3] 对象?

有没有办法调用传入对象指针的函数并在完成后返回对象指针?

【问题讨论】:

  • 永远不要使用自动存储持续时间存储/泄露变量的地址,因为这些对象在其作用域存在后将不复存在。函数void functionCall(Shape* [3]) 违反了这一点。
  • @UnholySheep:不,他不是。他将arrayOfShapes 声明为指向形状的指针数组。做你描述的事情是Shape (*ptr_toarray)[3];

标签: c++ pointers inheritance polymorphism


【解决方案1】:

您不能像这样在局部函数中创建形状,因为将局部变量的地址放入数组会使它们在其范围之外可用:

Shape shape;
arrayOfShapes[0] = &shape; // <<== Pointer to local

但是,您可以这样做:

arrayOfShapes[0] = new Shape;
arrayOfShapes[1] = new Point( 7, 11 );
arrayOfShapes[2] = new Circle( 3.5, 22, 8 );

这种方法在动态内存中创建形状,允许在函数返回时使用它们。

注意:尽管Circle 需要一个原点,但圆绝对不是一个点。因此,这个声明在逻辑上是不合理的:

class Circle : public Point // This implies that Circle is a Point

虽然您可以争辩说一个点是一个半径为零的圆,但像这样构造继承也是一个坏主意。更好的方法是使Circle 包含 Point 作为其来源:

class Circle : public Shape 
{
   public:
      const Point origin;
      // default constructor
      Circle( double r = 0.0, int x = 0, int y = 0 ):origin(x,y),
 radius(r) {}
      virtual void draw() const 
      {cout<<"draw circle("<<origin.getx()<<","<<origin.gety()<<","<<radius<<")\n";}
   private:
      double radius;   // radius of Circle
};

【讨论】:

  • 如果你要介绍new,你也应该说一下delete
  • 在这种情况下如何删除?删除形状?
  • @Justpee 是的,你调用delete arrayOfShapes[i]is 0、1 和2。为了使其正常工作,将virtual ~Shape() {} 析构函数添加到基类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 2011-06-24
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
相关资源
最近更新 更多