继承之虚函数

两个不同类的类对象一般是不能互相赋值的,但两个 具有 公有继承关系 的对象可赋值。
后代类的对象赋值给祖先类的对象 ,但 反之不成立 。此时被赋值的基类对象只能访问基类的公有成员,而不能访问派生类中新增的成员

虚函数

虚函数是在基类中以关键字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输出

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值