⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 virtualfun.cpp

📁 这我们老师对是面向对象程序设计(清华大学出版社)一书制作的PPT
💻 CPP
字号:

#include<iostream.h>
#include<math.h>
#include <string.h>

//【例12.1】 引入虚函数的原因示例。

class CStudent     //本科生类
{ 
//……
public:
	  void Calctuition()//计算本科生学费
{        
		cout<<"得到本科生学费计算结果!"<<endl;
	  }
	   //……
};
class CGraduateStudent:public CStudent     //研究生类,它是本科生类的派生类
{ 
//……
public:	
	 void Calctuition(){   //计算研究生学费
	     cout<<"得到研究生学费计算结果!"<<endl;
	}
	//……
};

void main12_1(void)
{
	CStudent s1,*p;      //B
	CGraduateStudent s2;
	p=&s1;
	p->Calctuition();     
	p=&s2;            //C
	p->Calctuition();    //D
	s2.Calctuition();
} 



//【例12.2】定义三个类:物体类、球体类和长方形体类,球体类和长方形体类分别为物体类的子类。它们都有一个求体积的函数。

class CShape
{
public:
	CShape(double x,double y)
	{XCode=x;YCode=y;}
	virtual double Volumn(){return 0.0;}
protected:
	double XCode,YCode;
};

class CBall:public CShape
{
public:
	CBall(double x,double y,double r):CShape(x,y)
	{Radius=r;}
	double Volumn()
	{return 3.14*0.75*Radius*Radius*Radius;}
protected:
	double Radius;
};

class CRectangle:public CShape
{
public:
	CRectangle(double x,double y,double h):CShape(x,y)
	{High=h;}
	double Volumn()
	{return XCode*YCode*High;}
protected:
	double High;
};

void Fun(CShape &p) 
{cout<<p.Volumn()<<endl;}

void main12_2(void)
{
	CBall b1(2.0,5.0,4.0);
	Fun(b1);
	CRectangle r1(2.0,4.0,6.0);
	Fun(r1);
}


//【例12.3】成员函数调用虚函数和非虚函数的比较

class CA
{
public:
	void fun1()
	{
		cout<<"CA::fun1()"<<'\t';
		fun2();
	}
	void fun2()
	{
		cout<<"CA::fun2()"<<'\t';
		fun3();
	}
	virtual void fun3()
	{cout<<"CA::fun3()"<<'\n';	}	
};

class CB:public CA
{
public:
	void fun2()
	{
		cout<<"CB::fun2()"<<'\n';
		fun3();
	}
	void fun3()
	{cout<<"CB::fun3()"<<'\n';	}
};

void main12_3(void)
{
	CB b;
	b.fun1();       //A
	CA a;
	a.fun1();
}


//【例12.4】虚函数与函数重载

class CBase
{
public:
	virtual void F1()
	{cout<<"F1 function of CBase!\n";}
	virtual void F2()
	{cout<<"F2 function of CBase!\n";}	
	void F3()
	{cout<<"F3 function of CBase!\n";}
};

class CDerive:public CBase
{
	void F1()
	{cout<<"F1 function of CDerive!\n";}
	void F2(int x)
	{cout<<"F2 function of CDerive!\n";}
	//int F2();      // A 错误,只有返回类型不同
	void F3()
	{cout<<"F3 function of CDerive!\n";}
};

void main12_4(void)
{
	CBase obj1,*ptr;
	CDerive obj2;
	ptr=&obj1;
	ptr->F1();    //调用基类版本
	ptr->F2();    //调用基类版本
	ptr->F3();    //调用基类版本
	ptr=&obj2;
	ptr->F1();    //动态连接,调用派生类版本
	ptr->F2();    //调用基类版本
	ptr->F3();    //调用基类版本
}


//【例12.5】基类构造函数调用虚函数

class CBase5
{
public:
	CBase5()
	{
		cout<<"调用基类的构造函数!\n";
		clone();
	}
	virtual void clone()
	{cout<<"调用基类中的clone()函数!\n";}
};

class CDerive5:public CBase5
{
public:
	CDerive5()
	{cout<<"调用派生类中的构造函数!\n";}
	void clone()
	{cout<<"调用派生类中的clone()函数!\n";}
};

void main12_5(void)
{
	CDerive5 obj;
	CBase5 *ptr=&obj;
	ptr->clone();          //A
}



//【例12.6】定义两个类,其中一个类是另一个类的子类。在子类中有一个指针类型的数据成员,
   //在构造函数中对该成员用new进行初始化,在析构函数中将该数据成员所占用的存储空间释放。

class Base6{
public:
	Base6(){cout<<"执行基类Base6的构造函数."<<endl;}
	//~Base6(){cout<<"执行基类Base6的析构函数."<<endl;}  //A  有问题
	virtual ~Base6(){cout<<"执行基类Base6的析构函数."<<endl;}   //正确
};

class Derived6:public Base6{
    int *x;
public:
	Derived6(){
		x=new int;
		cout<<"执行派生类Derived6的构造函数."<<endl;
	}
	~Derived6(){
	    delete x;     //B
	    cout<<"执行派生类Derived6的析构函数."<<endl;
	}

};

void main12_6()
{
    Base6 *p_base=new Derived6;   //C   或Base &p_base=* new Derived;
    delete p_base;              //    或 delete &p_base;
}



//【例12.7】利用纯虚函数定义抽象类。

class CAbs
{
protected:
	int x;
public:
	CAbs(){x=1000;}
	virtual void print()=0;      //纯虚函数
	void fun(){cout<<"调用抽象类CAbs中的非纯虚函数"<<endl;};
};

class CB7 : public CAbs
{
	int y;
public:
	CB7(){y=2000;}
	void print(){cout<<"y="<<y<<'\n';}      //对基类的纯虚函数重新定义
};

class CC : public CAbs
{
	int z;
public:
	CC(){z=3000;}
	void print(){cout<<"z="<<z<<'\n';}    //对基类的纯虚函数重新定义
};

void main12_7(void)
{
	//CAbs a;     //错误,抽象类不能有自己的实例
	CAbs *pa;   //创建抽象类的指针。
	//pa->print();  //错误,因为print()为纯虚函数,应去掉
	pa->fun();   //调用抽象类中的非纯函数
	CB7 b;
	pa=&b;     //将抽象类指针指向其派生类
	pa->print();
	CC c;
	CAbs &pb=c;   //创建抽象类的引用
	pb.print();
}



//【例12.8】抽象类的应用

class CPoint
{
public:
    CPoint(int i=0,int j=0)	{x0=i;y0=j;}
    virtual void set()=0;
    virtual void draw()=0;
protected:
    int x0,y0;
};

class CLine:public CPoint
{
public:
    CLine(int i=0,int j=0,int m=0,int n=0):CPoint(i,j)
    {x1=m;y1=n;}
    void set(){cout<<"CLine::set() called.\n";}
    void draw(){cout<<"CLine::draw() called.\n";}
protected:
    int x1,y1;
};

class CEllipse:public CPoint
{
public:
    CEllipse(int i=0,int j=0,int p=0,int q=0):CPoint(i,j)
    {x2=p;y2=q;}
    void set(){cout<<"CEllipse::set() called.\n";}
    void draw(){cout<<"CEllipse::draw() called.\n";}
protected:
    int x2,y2;
};

void DrawObj(CPoint *p)
{   p->draw();   }

void SetObj(CPoint *p)
{   p->set();   }

void main12_8(void)
{
    CLine *LineObj=new CLine;
    CEllipse *ElliObj=new CEllipse;
    DrawObj(LineObj);        //抽象类指针用作实参
    DrawObj(ElliObj);
    cout<<endl;
    SetObj(LineObj);
    SetObj(ElliObj);
    cout<<"\nRedraw the Object ...\n";
    DrawObj(LineObj);
    DrawObj(ElliObj);
}



//【例12.9】异质链表类的实现:定义三个类(CStudent、CTeacher、CStaff)和一个链表类CList,
      //其中链表类的每一个结点包含的数据为前三个类中某一种对象成员,且链表中的结点按姓名的次序进行排列。
/*分析:CStudent、CTeacher、CStaff这三个类中都有许多共同的属性和操作,我们将它们抽象为一个基类CPerson,
     且该类为抽象类。在CList链表类中,由于该链表中各结点的数据是可以不相同的(为CStudent、CTeacher、
	 CStaff三者类型的对象之一),因此在CList类的定义中可以定义一个CPerson类型的对象作为各结点中数据的通
	 用接口,这是引入抽象基类CPerson的另一个作用。*/



class CPerson{				//定义抽象的基类
	friend class CList;		//将CList声明为该类的友元类
protected:
	char name[20];			//姓名
	int age;				//年龄
	char add[40];			//地址
	char tele[15];			//电话
	static CPerson *ptr;		//指向该类对象的静态对象指针
	CPerson *next;			//指向下一个对象
public:
	CPerson(char *,int,char *,char *);		
	virtual void print();		//输出成员
	virtual void insert()=0;	//纯虚函数,插入成员
};

class CStudent9:public CPerson{	//定义学生类
	friend class CList;		//将CList声明为该类的友元类
	int level;				//班级
	float grade_point_average;	//平均成绩
public:
	CStudent9(char *,int,char *,char *,int,float);
	void print();
	void insert();
};

class CTeacher:public CPerson{	//定义教师类
	friend class CList;				//将CList声明为该类的友元类
	float salary;					//工资
public:
	CTeacher(char *,int,char *,char *,float);
	void print();
	void insert();
};

class CStaff:public CPerson{				//定义职员类
	friend class CList;				//将CList声明为该类的友元类
	float hourly_wages;				//计时工资
public:
	CStaff(char *,int,char *,char *,float);
	void print();
	void insert();
};

class CList{					//定义异质链表类
	CPerson *root;				//链表表头指针
public:
	CList(){root=0;}
	void insert_person(CPerson *node);	//插入一个结点
	void remove(char *name);			//移除一个结点
	void print_list();					//输出结点中的元素
};

CPerson::CPerson(char *name,int age,char *add,char *tele)
{
	strcpy(CPerson::name,name);
	strcpy(CPerson::add,add);
	strcpy(CPerson::tele,tele);
	CPerson::age=age;
	next=0;
}

void CPerson::print()
{
	cout<<"\nName: "<<name<<'\n';
	cout<<"Age:    "<<age<<'\n';
	cout<<"Address:"<<add<<'\n';
	cout<<"Telephone number:"<<tele<<'\n';
}

CStudent9::CStudent9(char *name,int age,char *add,char *tele,int level, 
					float grade_point_average) :CPerson(name,age,add,tele)	
{
	CStudent9::level=level;
	CStudent9::grade_point_average=grade_point_average;
}

void CStudent9::print()
{
	CPerson::print();		//输出从类CPerson中继承的属性
	cout<<"Grade point average:"<<grade_point_average<<'\n';
	cout<<"level:             "<<level<<'\n';
}

void CStudent9::insert()
{ptr=new CStudent9(name,age,add,tele,level,grade_point_average);}

CTeacher::CTeacher(char *name,int age,char *add,char *tele,float salary)
					:CPerson(name,age,add,tele)
{CTeacher::salary=salary;}

void CTeacher::print()
{
	CPerson::print();
	cout<<"Salary:       "<<salary<<'\n';
}

void CTeacher::insert()
{ptr=new CTeacher(name,age,add,tele,salary);}

CStaff::CStaff(char *name,int age,char *add,char *tele,float hourly_wage)
				:CPerson(name,age,add,tele)
{CStaff::hourly_wages=hourly_wages;}

void CStaff::print()
{
	CPerson::print();
	cout<<"Hourly_wages:"<<hourly_wages<<'\n';
}

void CStaff::insert()
{ptr=new CStaff(name,age,add,tele,hourly_wages);}

void CList::insert_person(CPerson *node)
{
	char key[20];
	strcpy(key,node->name);			//将插入对象的姓名赋给变量key
	CPerson *curr_node=root;
	CPerson *previous=0;
	while(curr_node!=0&&strcmp(curr_node->name,key)<0)
	{		//搜索所要插入的位置,注意结点是按姓名从小到大排列的
		previous=curr_node;			//插入位置的前一个结点指针
		curr_node=curr_node->next;		//插入位置的后一个结点指针
	}
	node->insert();		//调用虚函数insert(),并将要插入的对象指针赋给ptr
	node->ptr->next=curr_node;		//将ptr插入到链表中
	if(previous==0)
		root=node->ptr;
	else previous->next=node->ptr;
}

void CList::remove(char *name)
{			//从链表中移除一个结点,这里用该结点的name作为匹配条件
	CPerson *curr_node=root;
	CPerson *previous=0;
	while(curr_node!=0&&strcmp(curr_node->name,name)!=0)
	{		//搜索所要移除的结点
		previous=curr_node;
		curr_node=curr_node->next;
	}
	if(curr_node!=0&&previous==0)		//如果要移除的结点为链表头
	{
		root=curr_node->next;
		delete curr_node;
	}
	else if(curr_node!=0&&previous!=0) //如果要移除的结点不为链表头
	{
		previous->next=curr_node->next;
		delete curr_node;
	}
}

void CList::print_list()
{
	CPerson *cur=root;		//将指针cur指向链表头
	while(cur!=0){			//通过循环语句输出链表中的各个结点
		cur->print();		//根据不同类型的结点调用相应的函数print()
		cur=cur->next;	
	}	
}

CPerson *CPerson::ptr=0;

void main()
{
	CList people;
	CStudent9 str("Liuying",20,"Shanghai","03578395-465",3,80);
	CTeacher tea("Liming",35,"Beijing","01059186950-106",560.50);
	CStaff sta("Chenling",40,"Qingdao","05325895944",10);
	people.insert_person(&str);	
	people.insert_person(&tea);
	people.insert_person(&sta);
	people.print_list();
	people.remove("Chenling");
	people.remove("Liming");
	people.remove("WangChong");
	people.print_list();	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -