使用Pointer和普通变量来调用基类的函数之间的区别

时间:2014-08-06 22:56:59

标签: c++

// pointers to base class
#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
};

class Rectangle: public Polygon {
  public:
    int area()
      { return width*height; }
};

class Triangle: public Polygon {
  public:
    int area()
      { return width*height/2; }
};

int main () {
  Rectangle rect;
  Triangle trgl;
  //Polygon * ppoly1 = &rect;
  //Polygon * ppoly2 = &trgl;
  //ppoly1->set_values (4,5);
  //ppoly2->set_values (4,5);
    Polygon  ppoly1 = rect;
    Polygon  ppoly2 = trgl;
    ppoly1.set_values (4,5);
    ppoly2.set_values (4,5);

  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}

我知道注释行(当Polygon的指针用于调用函数时,它很好)。为什么我们需要一个指针,为什么我们不能只使用Polygon类型的普通变量。我尝试编译,它编译得很好,但没有给出正确的结果。为什么会这样?。

2 个答案:

答案 0 :(得分:4)

  • Rectangle/Triangle分配给Polygon时,您正在对对象进行切片。请参阅What is the slicing problem in C++?

  • 然后您打开(切片)副本上的set_values,因此当您计算原始多边形的区域时,实际上并未设置任何值。

  • 您的基类Rectangle也应定义虚拟析构函数,int area()应该是Polygon

  • 的常量纯虚方法

答案 1 :(得分:0)

因为你做的时候

Polygon  ppoly1 = rect;

您正在通过复制ppoly1对象中的值来创建另一个rect对象。因此,当您修改ppoly1的值时,实际上您并未影响rect中的值,当您复印文档并在副本上涂鸦时,您不会损坏原始文档。指针(或引用)代替与之前相同的对象:将&运算符视为获取对象的位置。如果复制指针,则复制的不是对象本身,而是仅复制其位置,该位置仍然是原始对象的位置。想想你把家庭住址写在纸上的陌生人身上:如果他抢走了地址写在纸张上的那所房子,你的同一所房子就会被抢劫。