第22卷第2期2006年4月
赤峰学院学报
Journal o f Ch ifeng C olleg e
V ol.22N o.2
A pr.2006
关于C++中虚函数的几个问题
张亚鹏
(赤峰学院 计算机科学与技术系,内蒙古 赤峰 024000)
  摘 要:论述了C++中虚函数的需要性、动态联编、虚函数与内联函数的问题.
关键词:C++;虚函数;需要性;动态联编;内联函数
中图分类号:T P311.1文献标识码:A文章编号:1673-260X(2006)02-0127-02
1 虚函数的需要性问题
派生类继承基类的特性,进行结构扩张,这种逐步扩张,逐步在各派生类中分解彼此不同特性的过程其实就是类的分解.使用继承时,子类希望重载成员函数,C++用一种称为多态性的技术来解决,可以确定哪个重载函数被调用,引入虚函数.
例如由交通工具派生出来的汽车类、飞机类,是具备更具体特性的描述的类,而对于交通工具这一个基类来说,它的特性是模糊的、广泛的,如果建立一个交通工具类的对象并没有实际意义,为了对这种没有必要建立对象的类进行约束,c++引入了抽象类的特性,这样的类唯一的用途是被继承.为了对抽象类的约束控制,引入了纯虚函数的定义.
一个类的成员函数为纯虚函数的意义在于让c++知道该函数并无意义,它的作用只是为派生类进行虚函数重载保留位置.
示例代码如下:
#include<i ostream>
us ing namespace std;
class Veh icle
{
pub lic:
Veh icle(float s peed,int total)
{
Veh icle::s peed=s peed;
Veh icle:total=total;
}
virtual void Sh ow Member()=0;//纯虚函数的定义
protected:
float s peed;
in t total;
};
class Car:public Veh icle
{
Car(int aird,float s peed,in t total):Vehicle(s peed,t otal)
{
Car::aird=aird;
}
v irtual v oid Show Member()//派生类成员函数重载
{
cou tνspeedν“│”νt otalν“│”νairdνendl;
}
protected:
int aird;
};
int main()
//V ehicle a(100,4);//错误,抽象类不能创建对象
Car b(250,150,4);
b.Sh ow Member();
system(“pause”);
}
C++中虚函数是为了实现多态性的机制,其核心理念是基类指针可以访问子类定义的函数.
在面向对象的编程过程中,我们总会设计出基类、子类构成类层次.如果某一函数(功能)需要重载,那么
我们分别要在基类和子类中书写代码.假如不使用虚函数,那么类层次结构必须要暴露在使用者(使用此功能的其他开发者)面前,否则使用者无法确定用哪一个类的函数,而且如果在此类层次结构中增加新类,那么也得需要使用者“知道”.为了介绍类层次结构和使用者之间的耦合,C++采用了虚函数机制.
2 动态联编问题
如果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现.当使用这个成员函数操作指针或引用所标识对象时,对该成员函数调用采取动态联编方式,即在运行时进行关联.
动态联编只能通过指针或引用标识对象来操作虚函数如果采用一般类型的标识对象来操作虚函数,则将采用静态联编方式调用虚函数
pub lic:.
.
721
下面给出一个动态联编的例子:
#include<i ostream.h>
class P oint
{
pub lic:
P oint(d oub le i,d ouble j){x=i;y=j;}
virtual d oub le Area()cons t{return0.0;}
private:
double x,y;
};
class Rectangle:public P oint
{
pub lic:
Rectangle(d ouble i,d oub le j,d oub le k,d oub le1);
//double Area()cons t{return w3h;}
virtual d oub le Area()cons t{return w3h;}
private:
double w,h;
};
Rectangle::Rectang le(d oub le i,d ouble j,double k,d ouble 1):P oint(i,j)
{
w=k;h=l;
}
v oid f un(Poin t&s)
{
G ou tνs.Area()νendl;
}
v oid main()
{
Rectangle rec(3.0,5.2,15.0,25.0);
fun(rec);
}
通过这个例子可以看到,派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数与基类中的被替换的虚函数之间满足如下条件:
(1)与基类的虚函数有相同的参数个数;
(2)其参数的类型与基类的虚函数的对应参数类型相同;
(3)其返回值或者与基类虚函数的相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的基类型是基类中被替换的虚函数所返回的指针或引用的基类型的子类型.3 虚函数与内联函数的问题
//.件中
class A
{
public:
 v irtual in t fl(){return a;}
 v irtual in t f2(){return a;}
protected:
 int a;
};
class B:public A
{
public:
 int fl(){return a;}
 inline int f2(){return a;}
 v irtual in line int f3(){return a;}
 inline v irtual int f4(){return a;}
 int f5(){return a;}
多态性与虚函数
 inline v oid g();
};
//.CPP文件中
v oid B::g()
{
 fl();
 f2();
 f3();
 f4();
 f5();
}
inline关键字是对实现的关键字,只有在实现的时候才有用,标准的内联函数的定义:
v oid f()://声明,没有in line关键字
inline v oid f(){…}//实现,头上加个inline就变成内联了
在声明的时候使用inline是完全没有意义的,所以f2, f3,f4,g的in line关键字都可以当它们不存在.而f5是内联,因为在声明时连函数一起实现的话,那么编译器自动将它作为内联.virtual关键字,只要在函数最初的声明中使用v irtual关键字,那么该函数和以后对它的继承覆盖,都是虚函数,不管它们是否在头文件中就实现,可以在th is中看见一个虚函数的展开.fl-f4都出现了virtual关键字,所以它们都是虚函数.g的inline是无效的,所以它就是一般的函数.于是,fl-f4都是虚函数,f5是内联函数,g是普通函数.
82 1