我需要对我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 = ▭
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
)都指向包含派生类对象的地址。
答案 0 :(得分:7)
由于virtual int area();
中没有声明CPolygon
,因此该方法通常与类CPolygon
的对象没有关联。
基本上,您希望方法查找在运行时发生(就像在Python,JavaScript和其他语言中完成的那样),但在C ++中它发生在编译时。上面的代码隐含地对C ++编译器说,“CRectangle
和CTriangle
有名为area
的方法,但它们彼此无关,也没有与CPolygon
有关。“
请记住,C ++编译器在编译时通常不会看到给定类的所有子类。
当我可以创建派生类的对象并调用它的区域函数并完成我的工作时,为什么我会使用基类的指针指向派生类的成员(通过实现虚函数)?
因为很少有代码知道它所使用的对象的每一个细节,并且通常没有必要知道,所以有简化。
例如,在这种情况下,如果您的整个代码是一个创建CTriangle
的函数,然后调用其area
方法来获取该区域,打印它并终止,那么是的,没有多大意义。代码只不过是一个带有额外verbage的美化计算器。
但是在现实世界中,你没有适合一个功能或源文件的所有东西。因此,一段代码可能知道它有一个指向CPolygon
的指针,但不是指向哪个特定的子类。然而,该代码需要知道它的区域。例如,给定横截面多边形和厚度的计算挤出体积的函数:
int extruded_volume(CPolygon* poly, int thickness)
{
return thickness * poly->area();
}
想象一下,这个函数在Extrusion.h
中声明并在Extrusion.cpp
中定义。此外,假设CPolygon
,CRectangle
和CTriangle
中的每一个单独在.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); }
...