📄 virtualfun.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 + -