0

我需要对我在此处阅读的特定段落进行一些解释。

所以在第一个例子中:

// 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()& ppoly2->area()?因为这两个指针(即使它们属于 class CPolygon)都指向包含派生类对象的地址。

4

2 回答 2

7

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

基本上,您希望方法查找发生在运行时(就像它在 Python、JavaScript 和其他语言中完成的那样),但在 C++ 中它发生在编译时。上面的代码隐含地告诉 C++ 编译器,“CRectangle并且CTriangle有命名的方法,area但是它们彼此没有任何关系,也没有任何关系CPolygon。”

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


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

因为很少有代码知道与它一起工作的对象的每一个小细节,而且通常不需要知道,所以需要进行简化。

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

但是在现实世界中,您并没有将所有东西都放在一个函数或源文件中的奢侈。所以一段代码可能知道它有一个指向CPolygon但不知道具体子类的指针。然而,该代码需要知道它的区域。例如,在给定横截面多边形和厚度的情况下计算挤出体积的函数:

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

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

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

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

因为我们使用了一个虚方法,所以CEllipse*可以在extruded_volume不改变后者代码的情况下将a 传递给它

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

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

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

于 2013-10-14T02:45:20.290 回答
0

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

有两种方法可以解决这个问题

投掷:

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

虚拟方法:

class CPolygon {
 public:
 virtual int area() { return (0); }
 ...
于 2013-10-14T02:49:32.367 回答