实例讲解C++编程中的虚函数与虚基类
虚函数
①
#include"stdafx.h"
#include<iostream>
usingnamespacestd;
classB0//基类B0声明
{
public:
voiddisplay(){cout<<"B0::display()"<<endl;}//公有成员函数
};
classB1:publicB0//公有派生类B1声明
{
public:
voiddisplay(){cout<<"B1::display()"<<endl;}//公有成员函数
};
classD1:publicB1//公有派生类D1声明
{
public:
voiddisplay(){cout<<"D1::display()"<<endl;}//公有成员函数
};
voidfun(B0*ptr)//普通函数
{//参数为指向基类对象的指针
ptr->display();//"对象指针->成员名"
}
voidmain()//主函数
{
B0b0;//声明基类B0类对象
B1b1;//声明B1类对象
D1d1;//声明D1类对象
B0*p;//声明B0类指针
p=&b0;//B0类指针指向B0类对象,
fun(p);
p=&b1;//B0类指针指向B1类对象,指向基类的指针也可以指向派生类。
fun(p);
p=&d1;//B0类指针指向D1类对象,指向基类的指针也可以指向派生类。
fun(p);
}
输出结果:
B0::display() B0::display() B0::display() Pressanykeytocontinue
类型兼容规则举例
#include"stdafx.h"
#include<iostream>
usingnamespacestd;
classB0//基类B0声明
{
public:
virtualvoiddisplay(){cout<<"B0::display()"<<endl;}//公有成员函数
};
classB1:publicB0//公有派生类B1声明
{
public:
voiddisplay(){cout<<"B1::display()"<<endl;}//公有成员函数
};
classD1:publicB1//公有派生类D1声明
{
public:
voiddisplay(){cout<<"D1::display()"<<endl;}//公有成员函数
};
voidfun(B0*ptr)//普通函数
{//参数为指向基类对象的指针
ptr->display();//"对象指针->成员名"
}
voidmain()//主函数
{
B0b0;//声明基类B0类对象
B1b1;//声明B1类对象
D1d1;//声明D1类对象
B0*p;//声明B0类指针
p=&b0;//B0类指针指向B0类对象,
fun(p);
p=&b1;//B0类指针指向B1类对象,指向基类的指针也可以指向派生类。
fun(p);
p=&d1;//B0类指针指向D1类对象,指向基类的指针也可以指向派生类。
fun(p);
}
输出结果:
B0::display() B1::display() D1::display() Pressanykeytocontinue
②
虚函数是为了实现某种功能而假设的函数,虚函数只能是类中的一个成员函数,不能是静态成员,使用关键字virtual用于在类中说明该函数是虚函数。虚函数更是为了实现面向对象的多态性而产生的,使用虚函数和多态
性能够简化代码长度,支持更简单的顺序,便于程序的调试,维护。
虚函数的定义方法:
classA
{
public:
virtualvoidfun();//definevirtualfunction
};
voidA::fun(){...}//memberfunctiondescribe
上面定义了一个虚函数,然后在类体外进行了函数的具体描述。
在类的继承当中,当基类中声明了某个虚函数,即使在派生类中没有声明虚函数,那么在以后的继承结构中都是
虚函数,当然如果有多重继承,在每个派生类中还是推荐对每个虚函数进行显式的声明。
为了说明虚函数在派生类中的应用,我写段代码作例子:
#include"stdio"
classcbase
{
public:
virtualvoidvfoo()
{
printf("vfoofromcbase/n");
};
voidfoo()
{
printf("foofromcbase/n");
}
};
classcderivd:publiccbase
{
public:
virtualvoidvfoo()
{
printf("vfoofromcderivd/n");
};
voidfoo()
{
printf("foofromcderivd/n");
};
};
intmain(intargc,char*argv[])
{
cbase*pbase=newcderivd();
pbase->foo();//非虚函数,根据指针类型决定调用哪个foo,本例指针类型为cbase,所以调用的是cbase::foo()
pbase->vfoo();//虚函数,调用的是派生类的vfoo
deletepbase;
cderivd*pd=newcderivd();
pd->foo();//非虚函数,本例指针类型为cderivd*,所以调用cderivd::foo();
pd->vfoo();
deletepd;
cderivdd;
d.foo();
d.vfoo();
((cbase)d).foo();//将d强行切割为cbase,这时调用的无论是foo还是vfoo都将是base的
((cbase)d).vfoo();
getchar();
return0;
}
程序在DevCPP下编译通过,输出:
foofromcbase vfoofromcderivd foofromcderivd vfoofromcderivd foofromcderivd vfoofromcderivd foofromcbase vfoofromcbase
虚基类
#include"stdafx.h"
#include<iostream>
#include<string>
usingnamespacestd;
classperson{//声明基类
protected:
intage;
charsex;
stringname;
public:
person(inta,chars,stringnam){
age=a;
sex=s;
name=nam;
}
};
classteacher:virtualpublicperson
{
protected:
stringtitle;
public:
teacher(inta,chars,stringnam,stringt):person(a,s,nam){
title=t;
}
};
classstudent:virtualpublicperson
{
protected:
floatscore;
public:
student(inta,chars,stringnam,floatsc):person(a,s,nam){
score=sc;
}
};
classgraduate:publicteacher,publicstudent
{
protected:
floatwdge;
public:
graduate(inta,chars,stringnam,stringt,floatsc,floatwd):person(a,s,nam),teacher(a,s,nam,t),student(a,s,nam,sc){
wdge=wd;
}
voidshow(){
cout<<name<<endl;
cout<<age<<endl;
cout<<sex<<endl;
cout<<title<<endl;
cout<<score<<endl;
cout<<wdge<<endl;
}
};
intmain(){
graduategr(22,'f',"k;asdjf;daf","klsdaf",89.5,79.5);
gr.show();
return0;
}
输出结果:
k;asdjf;daf 22 f klsdaf 89.5 79.5 Pressanykeytocontinue