虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,在基类的类定义中定义虚函数的一般形式:
virtual
函数返回值类型
虚函数名(形参表)
{
函数体
}
虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。
当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。
([20101028]
注:下行语义容易使人产生理解上的偏差,实际效果应为:
如存在:Base
->
Derive1
->
Derive2
及它们所拥有的虚函数func()
则在访问派生类Derive1的实例时,使用其基类Base及本身类型Derive1,或被静态转换的后续派生类Derive2的指针或引用,均可访问到Derive1所实现的func()。)
动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式:
指向基类的指针变量名->虚函数名(实参表)
或
基类对象的引用名
虚函数名(实参表)
虚函数是C++多态的一种表现
例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virtual(虚函数)。
使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。
如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual
函数名=0
我们把这样的函数(方法)称为纯虚函数。
如果一个类包含了纯虚函数,称此类为抽象类
。
虚函数的实例
#include<iostreamh>
class
Cshape
{
public:
void
SetColor(
int
color)
{
m_nColor=color;}
void
virtual
Display(
void)
{
cout<<"Cshape"<<endl;
}
private:
int
m_nColor;
};
class
Crectangle:
public
Cshape
{
public:
void
virtual
Display(
void)
{
cout<<"Crectangle"<<endl;
}
};
class
Ctriangle:
public
Cshape
{
void
virtual
Display(
void)
{
cout<<"Ctriangle"<<endl;
}
};
class
Cellipse
:public
Cshape
{
public:
void
virtual
Display(void)
{
cout<<"Cellipse"<<endl;}
};
void
main()
{
Cshape
obShape;
Cellipse
obEllipse;
Ctriangle
obTriangle;
Crectangle
obRectangle;
Cshape
pShape[4]=
{
&obShape,
&obEllipse,&obTriangle,
&
obRectangle
};
for(
int
I=
0;
I<
4;
I++)
pShape[I]->Display(
);
}
本程序运行结果:
Cshape
Cellipse
Ctriangle
Crectangle
条件
所以,从以上程序分析,实现动态联编需要三个条件:
1、
必须把动态联编的行为定义为类的虚函数。
2、
类之间存在子类型关系,一般表现为一个类从另一个类公有派生而来。
3、
必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。
常量指针 this 在成员函数内部用来访问与成员函数调用相关联的对象,简单来说就是,谁调用某个函数 this 就指向谁,例如 A a1(10);这句执行时,调用的是A(int x=0){this->x=x;}这个构造函数,this 就指向a1。
这个程序的输出
10
10
20
前两个结果没什么好说的,都很明了,关键是第三个。理论上,基类指针可以指向基类对象或者其派生类对象,然后调用相对应的虚函数,即是如果把B中的函数
void f(int a){cout<<y<<endl;}
改为
void f(){cout<<y<<endl;}
那么第三个结果是30,因为这里重定义了A中的虚函数。
如果保留为
void f(int a){cout<<y<<endl;}
则这个 f(int a) 会被认为是另外一个不同的函数(因为函数签名不一样),效果跟把f换成其他任何合法函数名是一样的(如abc),这里只是为了搞混别人。那么B中就没有重定义A中的f(),B中其实继承了A的f(),即B有一个跟A中一样的函数f(),功能就是输出X,所以最后输出的就是20
可以参考的内容:c++虚函数,继承,多态。。
你的问题在于,没有加入 destructor 去有效的除去你的 class
一种常用的表现方式:
virtual double cal() = 0;#include <cstdio>
class vT
{
public:
virtual double cal() = 0;
virtual ~vT(){}
};
class T: public vT
{
private:
double _val1, _val2;
public:
T( double v1=0, double v2=0 ): _val1(v1), _val2(v2) {}
double cal() { return _val1_val2; }
~T(){};
};
int main()
{
vT func1 = new T(20, 40);
printf( "ans = %f\n", func1->cal() );
delete func1;
}
你如果非要在你的 function 中加入参数,例如
virtual double area(double, double) = 0;你的 code 可以这样写:
#include <cstdio>class vT
{
public:
virtual double area(double, double) = 0;
virtual ~vT(){}
};
class T: public vT
{
public:
double area(double x, double y) { return xy; }
};
int main()
{
vT func = new T;
printf( "ans = %f\n", func->area(20, 40) );
}
觉得有帮助,不要忘了给我点赞哦
以上就是关于什么是虚函数全部的内容,包括:什么是虚函数、C++虚函数 。。。、c++程序 虚函数的使用 帮忙看看哪里出错了等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)