目录
关于多态性
向不同的对象发送同一个消息,不同的对象在接受时会产生不同的行为(即方法),也就是说每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。像前面所了解的函数的重载、运算符的重载都是多态现象。
在 C++中,多态性表现形式之一是:具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数。
多态性分为两类:静态多态性和动态多态性。
静态多态性是通过函数的重载实现的,由函数重载和运算符重载(运算符重载实质也是函数重载)形成的多态性属于静态多态性,要求是在编译时就知道调用函数的全部信息,因此,在程序编译时系统就能决定要调用的是哪个函数,静态多态性又称编译时的多态性。静态多态性的函数调用速度快、效率高,但缺乏灵活性,是在程序运行前就应决定执行的函数的方法。
动态多态性的特点是不在编译时确定调用哪个函数,而是在程序运行过程中才动态地确定操作所针对的对象,它又称为运行时的多态性。动态多态性是通过虚函数来实现的。
有关静态多态性的应用(函数的重载和运算符重载)前面已都提过了,下面主要介绍的是动态多态性和虚函数。在此之前,先写一个典型的例子(书上说是承上启下的例子),综合了前面一部分知识,进一步掌握编程思想和方法。
先建立一个 Point(点)类,包含数据成员 x ,y(坐标点)。以它为基类,派生出一个 Circle(圆)类,增加数据成员 r (半径)。再以 Circle 类为直接基类,派生出一个 Cylinder(圆柱体)类,再增加数据成员 h (高)。要求编写程序,重载运算符 “<<” 和 “>>“,使之能用于输出上类对象。
#include <iostream>
#include <math.h>
using namespace std;
class Point{
int x , y ;
public:
Point(int x1,int y1):x(x1),y(y1){}
void set_point(Point&);
void display(){
cout<<"第一次输出:"<<endl;
cout<<"x="<<x<<" "<<"y="<<y<<endl;
}
friend ostream& operator<<(ostream& ,Point& );
friend istream& operator>>(istream& ,Point& );
};
void Point::set_point(Point& p){
cin>>p ;
}
ostream& operator<<(ostream& output,Point& p){
output<<"x="<<p.x << '\t' << "y="<<p.y<<endl;
return output;
}
istream& operator>>(istream& input,Point& p){
input>>p.x>>p.y;
}
class Circle:public Point{
protected:
int r ;
public:
Circle(int x,int y,int r1):Point(x,y),r(r1){}
void set_circle(Circle& c){
cin>>c;
}
void display();
friend ostream& operator<<(ostream& ,Circle& c);
friend istream& operator>>(istream&,Circle& c);
};
void Circle::display(){
cout<<"第一次输出:"<<endl;
cout<<"r="<<r<<endl;
}
ostream& operator<<(ostream& output,Circle& c){
output<<"r="<<c.r<<endl;
return output;
}
istream& operator>>(istream& input,Circle& c){
input>>c.r;
return input;
}
class Cylinder:public Circle{
int h;
public:
Cylinder(int x,int y, int r,int h1):Circle(x,y,r),h(h1){}
void set_cylinder(Circle& c,Cylinder& cy){
cin>>c>>cy;
}
void display(){
cout<< h <<endl;
}
int area(){
return pow(r,2);
}
void V(){
int s;
s=area()*h;
cout<<"圆柱体体积是:"<<s<<endl;
}
friend ostream& operator<<(ostream& ,Cylinder& );
friend istream& operator>>(istream& ,Cylinder& );
};
ostream& operator<<(ostream& output,Cylinder& cy){
output<<"r="<<cy.r<<endl<<"h="<<cy.h;
return output;
}
istream& operator>>(istream& input,Cylinder& cy){
input>>cy.r>>cy.h;
return input;
}
int main(){
Point p(1,1);
p.display();
cout<<"第二次输入:"<<endl;
p.set_point(p);
cout<<"第二次输出:"<<endl;
cout<<p<<endl;
Circle c(1,1,1);
c.display();
cout<<"第二次输入:"<<endl;
c.set_circle(c);
cout<<"第二次输出:"<<endl;
cout<<c<<endl;
Cylinder cy(1,1,1,1);
cy.display();
cout<<"第二次输入:"<<endl;
cy.set_cylinder(c,cy);
cout<<"第二次输出:"<<endl;
cout<<cy<<endl;
cout<<"输出底面积:"<<cy.area()<<endl;
cy.V();
}
用虚函数实现动态多态性
1、虚函数的作用
我们会发现,在上面的一段程序中出现了同名覆盖的情况、、、
能否用同一个调用形式,能调用派生类和基类的同名函数
所谓虚函数,就是在基类声明时表示函数是虚拟的,并不是实际存在的函数,在派生类中才正式定义此函数。在程序运行期间,用基类指针或引用指向某一派生类对象,这样就能调用指针指向的派生类对象中的函数。
虚函数的使用允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。举一个前边提到过的例子:
#include <iostream>
#include <string>
using namespace std;
class Student{
protected:
int num;
string name;
float score;
public:
Student(int n,string nam, float s){
num= n;
name= nam;