C++ C++;多态性概念
我需要对我写的一段话作一些解释 在第一个例子中:C++ C++;多态性概念,c++,polymorphism,C++,Polymorphism,我需要对我写的一段话作一些解释 在第一个例子中: // 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 {
// 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;
}
//指向基类的指针
#包括
使用名称空间std;
类CPolygon{
受保护的:
int宽度、高度;
公众:
无效集合_值(整数a、整数b)
{宽度=a;高度=b;}
};
类CRectangle:公共CPolygon{
公众:
整数区域()
{返回(宽度*高度);}
};
类CTriangle:公共CPolygon{
公众:
整数区域()
{返回(宽度*高度/2);}
};
int main(){
斜角直肌;
CTriangle trgl;
CPolygon*ppoly1=&rect;
CPolygon*ppoly2=&trgl;
ppoly1->设置_值(4,5);
ppoly2->设置_值(4,5);
cout由于在CPolygon
中没有声明virtualint-area();
,因此该方法通常不会链接到类CPolygon
的对象
基本上,您希望在运行时发生方法查找(如Python、JavaScript和其他语言中所做的),但是在C++中,编译时发生。上面的代码隐含地说C++编译器,“
CRectangle
和CTriangle
具有名为area
的方法,但它们彼此无关,也与CPolygon
无关。”
<>请记住,C++编译器在编译时经常看不到给定类的所有子类。
当我可以创建一个派生类的对象并调用它的面积函数来完成我的工作时,为什么我要使用基类指针来指向派生类的成员(通过实现虚拟函数)
因为很少有代码知道它所处理的对象的每一个细节,而且通常是不需要知道的,所以需要进行简化
例如,在本例中,如果您的整个代码是一个函数,它创建了一个CTriangle
,然后调用其area
方法来获取区域、打印区域并终止,那么是的,没有什么意义。代码只不过是一个带有额外详细信息的美化计算器
但在现实世界中,你不可能在一个函数或源文件中实现所有功能。因此,一段代码可能知道它有一个指向CPolygon
的指针,但不知道具体的子类。然而,该代码需要知道它的面积。例如,一个函数在给定横截面多边形的情况下计算拉伸体积d a厚度:
int extruded_volume(CPolygon* poly, int thickness)
{
return thickness * poly->area();
}
假设此函数在extraction.h
中声明,并在extraction.cpp
中定义。此外,假设CPolygon
、CRectangle
和CTriangle
分别在.h
文件中声明,并在.cpp
文件中定义,并分别以类命名。然后>expression.h
只需要#包含“CPolygon.h”
,并且可以在不了解任何子类的情况下运行。当且仅当区域
是一个虚拟方法时,此方法才有效
这也允许以后添加CPolygon
的子类。例如,一个子类CEllipse
表示一个椭圆,其“宽度”和“高度”分别为其短轴和长轴长度:
class CEllipse: public CPolygon {
public:
int area ()
{ return M_PI * (width/2) * (height/2); }
};
由于我们使用了虚拟方法,因此可以将CEllipse*
传递到extrupted\u volume
,而不必更改后者的代码
如果area
不是虚拟方法,那么对于每个可能的多边形,您都需要一个单独版本的extracted\u volume
:
template<typename T>
int extruded_volume(T* poly, int thickness)
{
return thickness * poly->area();
}
模板
int拉伸体积(T*多边形,int厚度)
{
返回厚度*poly->area();
}
在这种情况下,代码膨胀是很小的,因为那里没有太多的代码,但在一个更大的系统中,这很可能是不可接受的。还要注意,调用卷的所有内容都可能也需要是模板。因为继承只向上工作。您可以调用在类或定义中定义的任何函数但不能在派生类中调用方法
有两种方法可以解决这个问题
演员阵容:
因为语言不是那样工作的。编译器不够聪明,无法确定在执行时,它们将指向area()所针对的对象
已定义,而且,这不是编译器的工作。您是否阅读了教程中解释虚拟成员的其余部分?@和256我确实阅读了它,但我仍然有这个问题。此外,为什么我要使用基类指针指向派生类的成员(通过实现虚拟函数)当我可以创建一个派生类的对象并调用它的area函数并完成我的工作时?想象一下一个方法必须处理任何类型的CPolygon
,才能完成它的工作。我们向它传递一个指向派生类对象的基类指针。然后我们的方法可以调用area()
而不知道它是什么类型的多边形。虚拟方法机制确保正确的区域()现在我们的方法可以处理任何类型的多边形,即使是新的子类,即<代码> CyPrimon < /Cuff> >,这会给程序员提供很大的能量。实际上,C++样式应该要求你使用<代码> DyrimixCase<代码>而不是<代码> StistaCase< /Cord>,并且必须检查<代码> DYNA的结果。mic_cast
,因为如果原始指针实际上没有指向派生类型(例如,它来自CTriangle
),它将返回空指针。C方式将所有警告抛到了脑后,并相信您的指针是合法的。使用static_-cast
从派生类转到其基类。此外,*
位于类型名称之后。在某些代码中,您会发现dynamic_-cast
在if(CRectangle*pr=dynamic_-cast(ppoly1)){cout-area()形式中使用@MikeDeSimone实际上,在这种情况下,一个static\u cast
就足够了(只是因为
((*CRectangle)ppoly1)->area() //C style
static_cast<*CRectangle>(ppoly1)->area //C++ style
class CPolygon {
public:
virtual int area() { return (0); }
...