C ++多态性概念

时间:2013-10-14 02:36:26

标签: c++ polymorphism

我需要对我read here的特定段落做一些解释。

所以在第一个例子中:

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

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

class CRectangle: public CPolygon {
public:
int area ()
  { return (width * height); }
};

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

int main () {
CRectangle rect;
CTriangle trgl;
CPolygon * ppoly1 = &rect;
CPolygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << rect.area() << endl;
cout << trgl.area() << endl;
return 0;
}

为什么我不能简单地提及ppoly1->area()&amp; ppoly2->area()?因为这两个指针(即使它们是类CPolygon)都指向包含派生类对象的地址。

2 个答案:

答案 0 :(得分:7)

由于virtual int area();中没有声明CPolygon,因此该方法通常与类CPolygon的对象没有关联。

基本上,您希望方法查找在运行时发生(就像在Python,JavaScript和其他语言中完成的那样),但在C ++中它发生在编译时。上面的代码隐含地对C ++编译器说,“CRectangleCTriangle有名为area的方法,但它们彼此无关,也没有与CPolygon有关。“

请记住,C ++编译器在编译时通常不会看到给定类的所有子类。


  

当我可以创建派生类的对象并调用它的区域函数并完成我的工作时,为什么我会使用基类的指针指向派生类的成员(通过实现虚函数)?

因为很少有代码知道它所使用的对象的每一个细节,并且通常没有必要知道,所以有简化。

例如,在这种情况下,如果您的整个代码是一个创建CTriangle的函数,然后调用其area方法来获取该区域,打印它并终止,那么是的,没有多大意义。代码只不过是一个带有额外verbage的美化计算器。

但是在现实世界中,你没有适合一个功能或源文件的所有东西。因此,一段代码可能知道它有一个指向CPolygon的指针,但不是指向哪个特定的子类。然而,该代码需要知道它的区域。例如,给定横截面多边形和厚度的计算挤出体积的函数:

int extruded_volume(CPolygon* poly, int thickness)
{
    return thickness * poly->area();
}

想象一下,这个函数在Extrusion.h中声明并在Extrusion.cpp中定义。此外,假设CPolygonCRectangleCTriangle中的每一个单独.h文件中声明并在.cpp文件中定义分别以类命名。然后Extrusion.h只需要#include "CPolygon.h",并且可以在不了解各种子类的情况下终其一生。 当且仅当area是虚方法时,此方法才有效。

这也允许稍后添加CPolygon的子类。例如,一个子类CEllipse表示一个椭圆,其“宽度”和“高度”分别是它的次轴和长轴:

class CEllipse: public CPolygon {
public:
int area ()
  { return M_PI * (width/2) * (height/2); }
};

由于我们使用了虚拟方法,因此可以将CEllipse*传递给extruded_volume,而无需更改后者的代码

如果area 不是虚拟方法,那么每个可能的多边形都需要单独版本的extruded_volume

template<typename T>
int extruded_volume(T* poly, int thickness)
{
    return thickness * poly->area();
}

在这种情况下,代码膨胀是次要的,因为那里的代码不多,但在更大的系统中,这可能是不可接受的。另请注意,调用extruded_volume的所有内容也可能需要成为模板。

答案 1 :(得分:0)

因为继承只能向上运行。您可以调用在类中定义的或在该类父类中定义的任何函数,但不能在派生类中调用方法。

有两种解决方法

角色:

((*CRectangle)ppoly1)->area() //C style
static_cast<*CRectangle>(ppoly1)->area //C++ style 

虚拟方法:

class CPolygon {
 public:
 virtual int area() { return (0); }
 ...