举个具体的例子,动态多态有啥用啊

如题啊。...
2026年09月23日 20:05
有2个网友回答
网友(1):

封装性、继承性和多态性构成了面向对象程序设计语言的三大特性。
封装性是基础,继承性是关键,多态性是扩充。
多态性是指对不同类的对象发出相同的消息将会有不同的行为。
消息主要是指对类的成员函数的调用,不同的行为是指不同的实现。
本部分主要介绍多态性;动态联编;虚函数;纯虚函数和抽象类等重要内容。

函数重载
函数重载是多态性的一种简单形式,它是指允许在相同的作用域内,相同的函数名对应着不同的实现。
函数重载的条件是要求函数参数的类型或个数有所不同。对成员函数的重载有以下三种表达方式:
1、在一个类中重载;
2、在不同类中重载;
3、基类的成员函数在派生类中重载。

具有相同名字的重载函数是在编译时区分的,有以下三种区分方法:
1、根据参数的特征加以区别,例如:
show(int, char);
show (char*, float);
2、使用类作用域符“::”加以区分,例如:
Circle::show();
Point::show();
3、根据类对象加以区分,例如:
acircle.show()调用Circle::show()
apoint.show()调用Point::show()

除了函数重载这种简单形式之外,C++ 还提供了一种更为灵活的特征机制——虚函数。
虚函数允许函数调用与函数体的联系在运行时才给出。当需要同一接口、多种实现时,这种功能显得尤其重要。
在讲述虚函数的概念之前,先介绍子类型及静态联编和动态联编的相关内容。

子类型
有一个特定的类型S,当且仅当它至少提供了类型T 的行为,则称类型S 是类型T 的子类型。
在继承关系中,若类B 是类A 以公有继承形式产生的派生类,则类B 包含了类A 的行为,并且它本身还可具有新的行为,可称类B 是类A 的一个子类型。
若类B 是类A 的子类型,则类A 对象可操作的函数,类B 的对象也可以进行操作,称类B 适应类 A。

子类型的重要作用就在于类型适应,即在公有继承方式下,派生类的对象、指向派生类对象的指针和派生类对象的引用都适应于基类的对象、指向基类对象的指针和基类对象的引用所能使用的场合。
子类型关系是不可逆的。已知类B 是类A 的子类型,而认为类A 也是类B 的子类型是错误的。

例如:假设M 是基类,N 是以公有继承方式产生的派生类,函数void fun(M& P) 以基类M 的引用作为形参数,则
void main()
{
M m(7),q;
N n(3,8);
q=n; //派生类对象赋与基类对象
M *pm=new M(6);
N *pn=new N(5,9);
pm=pn; //派生类指针赋给基类指针
fun(*pn); //实参为派生类传递给基类的引用
}
由于子类型的类型适应性,main()中被注释的语句都是合法的。

根据类型适应性,在公有继承方式下,指向基类和派生类的指针变量是相关的。如果B 是基类,D 是从B 公有派生出来的派生类,则在C++ 中,指向基类B 的指针P 也可以指向派生类D。当P 指向派生类D 的对象时,利用指针P 可以访问从基类B 继承的成员,但派生类D 自己定义的成员不能用P 访问(除非用显式类型转换)。

例如:下面是指向基类对象的指针指向派生类对象,从而访问从基类继承的成员的例子。

#include
#include
class B
{
char name[80];
public:
void put_name(char *s)
{ strcpy(name,s); }
void show_name()
{ cout< };
class D: public B
{
char phone_num[80];
public:
void put_phone(char *num)
{
strcpy(phone_num,num);
}
void show_phone()
{
cout< }
};
main()
{
B *p; B Bobj; D *dp; D Dobj;
p=&Bobj;
p->put_name(“Zhang Fang”);
p=&Dobj;
p->put_name(“Wang Ming”); //访问从基类继承的成员函数
Bobj.show_name();
Dobj.show_name();
dp=&Dobj;
dp->put_phone(“83768493”); //访问自己的成员
dp->show_phone();
p->show_phone(); //error!指向基类指针不能访问派生类定义的成员
((D *)p)->show_phone(); //强行类型转换
}
注意:希望用基类指针访问其公有派生类的特定成员,必须将基类指针用显式类型转换为派生类指针。根据类型适应性的原则,一个指向基类的指针可以用来指向其公有派生类的任何对象,这是C++ 实现运行时多态性的关键。

网友(2):

纯虚函数和抽象类
纯虚函数是一种特殊的虚函数,是一种没有具体实现的虚函数,其定义格式如下:

class <类名>
{
virtual <类定义说明符><函数名>(<参数表>)=0;
//…
};

A virtual function is “made pure” by the initializer =0;

例如:
class Shape
{
public:
virtual void draw()=0;//纯虚函数
virtual bool is_closed()=0; //纯虚函数
//…
};

一个类如果它存在纯虚函数,那么它就是抽象类,它不能用来定义对象。
Shape S; //error: Creating the object of abstract class Shape
注:一个抽象类只能用来作为其他类的基类,起到接口的作用

如果纯虚函数在派生类中没有定义,那么在派生类中它仍然是纯虚函数,因此,派生类也是抽象类。
例如:
class B
{
public:
virtual void init()=0;
virtual write(char *pstring)=0;
};
class D: public B //write() 没有定义,类D是抽象类
{
public:
virtual void init()
{ //…. }
};

例如:下面举一个计算某些几何图形的面积之和的例子,以说明纯虚函数及抽象类的应用。
#include
//--
class Shape //抽象类
{
public:
virtual double Area() const=0;//纯虚函数
};
//--
class Circle: public Shape
{
public:
Circle(double r)
{ R=r; }
double Area() const
{ return 3.14*R*R; }
private:
double R;
};
class Trapezoid: public Shape
{
public:
Trapezoid(double t, double b, double h)
{ T=t; B=b; H=h; }
double Area() const
{ return 0.5*(T+B)*H; }
private:
double T,B,H;
};
//--
class Square: public Shape
{
public:
Square(double s)
{ S=s; }
double Area() const
{ return S*S; }
private:
double S;
};
double Compute(Shape *s[ ], int n)
{
double sum=0;
for(int i=0; i sum+=s[i]->Area();
return sum;
}
void main()
{
Shape* ptr[3];
ptr[0]=new Circle(8.5);
ptr[1]=new Trapezoid(12.0,8.0,6.0);
ptr[2]=new Square(6.8);
cout<<"Area's sum="< for(int i=0; i<3; i++)
delete ptr[i];
}
输出结果:

Area’s sum=333.105

程序分析:
1、该程序定义了4个类,其关系如前图所示;
2、类Shape 定义为抽象类,相当于Circle 等3个类的根,Shape 类中定义纯虚函数Area(),在它的3个派生类中定义其具体实现;
3、Compute()为计算面积和的函数。

An important use of abstract classes is to provide an interface without exposing any implementation details, for example, an operating system might hide the detail of its device drivers behind an abstract class:
class character_device
{
public:
virtual int open(int opt)=0;
virtual int close(int opt)=0;
virtual int read(char *p, int n)=0;
virtual int write(const char *p, int n)=0;
virtual int ioct1(int …)=0;
virtual ~character_device() { } //virtual destructor
};

虚析构函数
构造函数不能说明为虚函数,而析构函数可以说明为虚函数。其方法是在析构函数前加上关键字virtual 说明符。
如果一个基类的析构函数被说明为虚函数,则其派生类中的析构函数也是虚析构函数,可省略virtual 说明符。
虚析构函数可以采用动态联编,可在运行时选择析构函数,能确保析构函数说明为虚析构函数的正确执行。
因此,在继承的情况下,将基类中的析构函数说明为虚析构函数是没有坏处的。