文章目录
第八章多态性与虚函数
一、 多态性的概念
- 向不同的对象发送同一个消息,会产生不同的行为或方法。静态多态性通过函数重载实现,动态多态性通过虚函数来实现
1.例子:
要求先建立一个Point(点)类,包含数据成员x,y(坐标点)。以它为基类,派生出一个Circle(圆)类,增加数据成员r(半径),再以Circle类为直接基类,派生出一个Cylinder(圆柱体)类,再增加数据成员h(高)。要求编写程序,重载运算符”<<“和”>>“,使之能输出以上类对象。
1.先声明Point(点)基类
#include <iostream.h>
//using namespace std;
//声明类Point
class Point
{public:
Point(float=0,float=0);
void setPoint(float,float);
float getX() const {return x;}
float getY() const {return y;}
friend ostream & operator<<(ostream &,const Point &);
protected:
float x,y;
};
//定义Point类的成员函数
//Point的构造函数
Point::Point(float a,float b)
{x=a;y=b;}
//设置x和y的坐标值
void Point::setPoint(float a,float b)
{x=a;y=b;}
//输出点的坐标
ostream & operator<<(ostream &output,const Point &p)
{output<<"["<<p.x<<","<<p.y<<"]"<<endl;
return output;
}
//测试是否上述代码正确
int main()
{Point p(3.5,6.4);
cout<<"x="<<p.getX()<<",y="<<p.getY()<<endl;
p.setPoint(8.5,6.8);
cout<<"p(new):"<<p<<endl;
return 0;
}
2.在声明Point(点)的Circle(圆)派生类
class Circle:public Point
{public:
Circle(float x=0,float y=0,float r=0);
void setRadius(float);
float getRadius() const;
float area () const;
friend ostream &operator<<(ostream &,const Circle &);
private:
float radius;
};
Circle::Circle(float a,float b,float r):Point(a,b),radius(r){}
void Circle::setRadius(float r)
{radius=r;}
float Circle::getRadius() const {return radius;}
float Circle::area() const
{return 3.14159*radius*radius;}
ostream &operator<<(ostream &output,const Circle &c)
{output<<"Center=["<<c.x<<","<<c.y<<"], Radius="<<c.radius<<", area="<<c.area()<<endl;
return output;
}
//c
int main()
{Circle c(3.5,6.4,5.2);
cout<<"original circle:\nx="<<c.getX()<<", y="<<c.getY()<<", r="<<c.getRadius()
<<", area="<<c.area()<<endl;
c.setRadius(7.5);
c.setPoint(5,5);
cout<<"new circle:\n"<<c;
Point &pRef=c;
cout<<"pRef:"<<pRef;
return 0;
}
3.在声明Circle(圆)的Cylinder(圆柱体)派生类
class Cylinder:public Circle
{public:
Cylinder (float x=0,float y=0,float r=0,float h=0);
void setHeight(float);
float getHeight() const;
float area() const;
float volume() const;
friend ostream& operator<<(ostream&,const Cylinder&);
protected:
float height;
};
Cylinder::Cylinder(float a,float b,float r,float h)
:Circle(a,b,r),height(h){}
void Cylinder::setHeight(float h){height=h;}
float Cylinder::getHeight() const {return height;}
float Cylinder::area() const
{ return 2*Circle::area()+2*3.14159*radius*height;}
float Cylinder::volume() const
{return Circle::area()*height;}
ostream &operator<<(ostream &output,const Cylinder& cy)
{output<<"Center=["<<cy.x<<","<<cy.y<<"], r="<<cy.radius<<", h="<<cy.height
<<"\narea="<<cy.area()<<", volume="<<cy.volume()<<endl;
return output;
}
//测试
int main()
{Cylinder cy1(3.5,6.4,5.2,10);
cout<<"\noriginal cylinder:\nx="<<cy1.getX()<<", y="<<cy1.getY()<<", r="
<<cy1.getRadius()<<", h="<<cy1.getHeight()<<"\narea="<<cy1.area()
<<", volume="<<cy1.volume()<<endl;
cy1.setHeight(15);
cy1.setRadius(7.5);
cy1.setPoint(5,5);
cout<<"\nnew cylinder:\n"<<cy1;
Point &pRef=cy1;
cout<<"\npRef as a point:"<<pRef;
Circle &cRef=cy1;
cout<<"\ncRef as a Circle:"<<cRef;
return 0;
}
二、多态性的实现
1.用虚函数实现多态
#include <iostream>
#include <string>
using namespace std;
class Student
{public:
Student(int,string,float);
void display();
protected:
int num;
string name;
float score;
};
Student::Student(int n,string nam,float s)
{num=n;name=nam;score=s;}
void Student::display()
{cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<"\n\n";}
class Graduate:public Student
{public:
Graduate(int,string,float,float);
void display();
private:
float pay;
};
void Graduate::display()
{cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<"\npay="<<pay<<endl;}
Graduate::Graduate(int n,string nam,float s,float p):Student(n,nam,s),pay(p){}
int main()
{Student stud1(1001,"Li",87.5);
Graduate grad1(2001,"Wang",98.5,563.5);
Student *pt=&stud1;
pt->display();
pt=&grad1;
pt->display();
return 0;
}
- 输出结果是没有wage这一个内容的
- 但是在基类Student中的void display()前加上virtual,输出结果就会有wage——因为在声明派生类display函数时会被重载为派生类中的display
2.在何种情况下用到虚函数
- 只能将类的成员函数声明为虚函数
- 不能定义一个与被声明为虚函数有相同的参数(数据个数及类型)和返回值相同的且同名的非virtual函数
3.纯虚函数
- 定义:virtual 函数类型 函数名 (参数列表)=0;
- 基类用不到,但派生类可能会用到。