虚函数
•虚函数是在基类中以关键字virtual说明,并在派生类中重新定义的一个非静态成员函数
–基类的虚函数在派生类中仍然是虚函数
–在派生类中重定义继承成员虚函数时,即使没有保留字virtual,该函数仍然是虚函数(但为了更好地表达这些函数的实质,最好加上这一保留字virtual)。
基类中的虚函数必须具有public或protected访问权限,且派生类必须以公有继承方式从基类派生
虚函数就像是一个接口,能把相同的函数从基类接通到子类
含有虚函数的类可以直接创建:
#include<bits/stdc++.h>
using namespace std;
class Animal{
public:
virtual void speak()=0;
};
class Tiger:public Animal{
private:
string nam;
int age;
public:
Tiger(){};
Tiger(string a,int b):nam(a),age(b){};
virtual void speak(){
cout<<"Hello,I am "<<nam<<",AOOO."<<endl;
}
};
class Pig:public Animal{
private:
string nam;
int age;
public:
Pig(){};
Pig(string a,int b):nam(a),age(b){};
virtual void speak(){
cout<<"Hello,I am "<<nam<<",HENGHENG."<<endl;
}
};
class Dog:public Animal{
private:
string nam;
int age;
public:
Dog(){};
Dog(string a,int b):nam(a),age(b){};
virtual void speak(){
cout<<"Hello,I am "<<nam<<",WangWang."<<endl;
}
};
class Duck:public Animal{
private:
string nam;
int age;
public:
Duck(){};
Duck(string a,int b):nam(a),age(b){};
virtual void speak(){
cout<<"Hello,I am "<<nam<<",GAGA."<<endl;
}
};
int main(){
int n;
cin>>n;
while(n--)
{
string s,n;
int a;
cin>>s>>n>>a;
if(s=="Tiger")
{
Tiger x(n,a);
x.speak();
}
else if(s=="Pig")
{
Pig x(n,a);
x.speak();
}
else if(s=="Dog")
{
Dog x(n,a);
x.speak();
}
else if(s=="Duck")
{
Duck x(n,a);
x.speak();
}
else cout<<"There is no "<<s<<" in our Zoo."<<endl;
}
return 0;
}
也可以用对象指针:
#include<bits/stdc++.h>
using namespace std;
const int yf[20]={0,31,28,31,30,31,30,31,31,30,31,30,31};
class CDate{
private:
int y,m,d;
public:
CDate(){};
CDate(int a,int b,int c):y(a),m(b),d(c){};
int dis(CDate& p){
int f=1;
if(p.y>y)
{
f=0;
}
else if(p.y==y&&p.m>m)
{
f=0;
}
else if(p.y==y&&p.m==m&&p.d>d)
{
f=0;
}
if(!f) {
return -1;
}
int sum1=0,sum2=0;
sum1=(y-p.y)*365;
for(int i=1;i<=m-1;i++) sum1+=yf[i];
for(int i=1;i<=p.m-1;i++) sum2+=yf[i];
sum1+=d;
sum2+=p.d;
// cout<<endl<<sum1<<"** "<<sum2<<endl;
return sum1-sum2;
}
};
class Pet{
protected:
string name;
double len,wei;
CDate cur;
public:
Pet(){};
Pet(string a,double b,double c,CDate d):name(a),len(b),wei(c),cur(d){};
virtual void display(CDate day)=0;
};
class Cat:public Pet{
public:
Cat(){};
Cat(string a,double b,double c,CDate d):Pet(a,b,c,d){};
virtual void display(CDate day){
int d=cur.dis(day);
if(d==-1)
{
cout<<"error"<<endl;
return ;
}
len+=0.1*d;
wei+=0.2*d;
cout<<name;
printf(" after %d day: length=%.2lf,weight=%.2lf\n",d,len,wei);
}
};
class Dog:public Pet{
public:
Dog(){};
Dog(string a,double b,double c,CDate d):Pet(a,b,c,d){};
virtual void display(CDate day){
int d=cur.dis(day);
if(d==-1)
{
cout<<"error"<<endl;
}
len+=0.2*d;
wei+=0.1*d;
cout<<name;
printf(" after %d day: length=%.2lf,weight=%.2lf\n",d,len,wei);
}
};
int main(){
int n;
cin>>n;
Pet *pt;
int a,b,c;
cin>>a>>b>>c;
CDate test(a,b,c);
while(n--)
{
int r,l,w,y,m,d;
string name;
cin>>r>>name>>l>>w>>y>>m>>d;
CDate cur(y,m,d);
if(r==1)
{
Cat* p=new Cat(name,l,w,cur);
p->display(test);
delete p;
}
else
{
Dog* p=new Dog(name,l,w,cur);
p->display(test);
delete p;
}
}
return 0;
}
关于怎么计算日期差,想到了个很巧妙的思路:创建一个常量数组来表示每个月份的天数,在把这一年中过的所有天数加起来相减。要注意两点:一是没有考虑闰年,否则还要在年份差和2月上修改。二是要注意计算时是加到当下月份-1,不要把当前月份算进去。
纯虚函数和抽象类(只能创建对象指针,不能是对象)
纯虚函数:在基类中没有具体实现的虚函数。
如果基类中包括有纯虚函数,那么在任何派生类中都必须重定义该函数,因为它们不能直接使用从基类继承下来的虚函数。
纯虚函数的一般形式为:
virtual <函数返回类型> <函数名>(<参数表>) = 0;
(花括号都没有)
包含纯虚函数的类称做抽象类。只要包含了都是抽象类,不能创建对象,只能创指针
由于无法实例化一个含纯虚函数的抽象类,因而不能创建抽象类的对象。
抽象类不能用作变量类型、函数返回和显式转换的类型,但可定义指向抽象类的指针或引用
#include<bits/stdc++.h>
using namespace std;
const double pi=3.14159;
class Shape{
protected:
double x,y,s,v;
string name;
public:
Shape(){};
Shape(double a,double b):x(a),y(b){};
virtual string getN(){return name;}
virtual double getX(){return x;}
virtual double getY(){return y;}
virtual double getS(){return 0.0;}
virtual double getV(){return 0.0;}
virtual void shapeName()=0;
};
class Point:public Shape{
public:
virtual void shapeName(){
name="Point";
}
Point(){};
Point(double a,double b):Shape(a,b){
shapeName();
};
};
class Circle:public Point{
protected:
double r;
public:
virtual void shapeName(){
name="Circle";
}
Circle(){};
Circle(double a,double b,double c):Point(a,b),r(c){
shapeName();
};
virtual double getS(){
return pi*r*r;
}
};
class Cylinder:public Circle{
protected:
double h;
public:
virtual void shapeName(){
name="Cylinder";
}
Cylinder(){};
Cylinder(double a,double b,double c,double d):Circle(a,b,c),h(d){
shapeName();
};
virtual double getS(){
return pi*2*r*h+2*pi*r*r;}
virtual double getV(){
return pi*r*r*h;
}
};
void Print(Shape* p)
{
cout<<p->getN();
printf("--(%.1lf,%.1lf)--%d--%d\n",p->getX(),p->getY(),(int)p->getS(),(int)p->getV());
}
int main(){
double a,b,c,d;
cin>>a>>b;
Point *p=new Point(a,b);
Print(p);
delete p;
cin>>a>>b>>c;
Circle *pp=new Circle(a,b,c);
Print(pp);
delete pp;
cin>>a>>b>>c>>d;
Cylinder *ppp=new Cylinder(a,b,c,d);
Print(ppp);
delete ppp;
return 0;
}
注意double不能直接%d输出,否则是随机值而非转化为int输出