C++][基础知识 5] 虚函数

五 虚函数
VC++中的虚函数主要用来实现程序运行的多态性。所谓多态性是指发出同样的消息(如函数的调用)被不同类型的对象接受时导致不同的行为。利用多态性,用户只需发送一般形式的消息,而将所有的实现留给接受消息的对象。对象根据所接受到的消息而做出相应的操作。
多态性是面向对象程序设计的重要特征之一。它与前面讲过的封装性和继承性构成了面向对象程序设计的三大特征。这三大特性是相互关联的。封装性是基础,继承性是关键,多态性是补充。
VC++中的多态可以分为两种,一种是编译时的多态性,一种是运行时的多态性。编译时的多态性主要是通过函数的重载和运算符的重载来实现,它在程序运行之前(编译时)就能够确定其实现的方法。运行时的多态性则要等到程序运行时才能确定程序的具体执行情况,它主要通过虚函数来实现。
 虚函数的定义及使用
如果将函数定义为虚函数,则表示函数的具体实现是不确定的,相同的调用形式要根据运行时不同的对象来确定其实现方式。它与函数的重载不同,函数的重载根据其调用形式(函数的参数)就能够确定其实现方式。
在类中,如果在某一函数的前面加上关键字”virtual”,则表示将该函数说明为虚函数。虚函数一定是类的成员函数,其多态性要通过类的继承关系来实现。如果将类中的函数说明为虚函数,则该类的派生类中相同原型的函数(同名,且参数类型,顺序以及个数都相同)均具有虚特性而不管是否有关键子”virtual”修饰。例如:

#include<iostream.h>
class A{
public:
virtual void fun() //A行
{cout<<"类A中的函数\n";}
};
class B:public A{
public:
void fun()
{cout<<"类B中的函数\n";}
};
void main()
{
A a1,*p;
B b1;
p=&a1;
p->fun(); //B行
p=&b1;
p->fun(); //C行
}

程序运行结果:
类A中的函数
类B中的函数
程序基类中A行将函数fun()说明为虚函数,则在类A的派生类B中函数fun()虽然没有用”virtual”修饰,它也为虚函数,在主函数中的B行和C行虽然调用形式相同,但两次调用时指针p所指向的对象不同,因而调用的是不同对象的成员函数,所以其输出也不同。
在说明和使用虚函数时,应该注意以下几点:
(1) 虚函数同于不同的有继承关系的类中的相同原型函数(同名,且参数类型,顺序以及个数都相同),仅函数名相同则属于函数的重载;单独的一个虚函数没有实际的意义。
(2) 虚函数的多态性必须通过相同的指针来实现,通过对象名来调用虚函数不能体现虚函数的多态性。一般来说,实现虚函数的多态性是通过基类的指针指向不同的对象来处理虚函数的。
(3) 虚函数是类的成员函数,但不能是静态成员函数,更不能是友元函数。友元函数不是类的成员。
(4) 如果派生类中没有重新定义虚函数,则不能体现虚函数的多态性。
 纯虚函数
如果基类中的某个函数的功能暂时还不能确定或没有必要先确定,则可以先不具体定义此函数而先将其说明为纯虚函数,其具体实现在派生类中定义。纯虚函数的定义方式是将一个明确了函数原型的虚函数赋以初值0。例如:

#include<iostream.h>
class A{
protected:
int a;
public:
A(int x){a=x;}
virtual void fun(int)=0; //A行
};
class B:public A{
int b;
public:
B(int x,int y):A(y){b=x;}
void fun(int x) //B行
{
cout<<a+x<<'\n';
cout<<b+x<<'\n';
}
};
void main()
{
A *p; //C行
B b1(2,6);
p=&b1;
p->fun(1); //D行
}

程序在基类A中将函数void fun(int)定义为纯虚函数(A行)。由于基类A含有纯虚函数,纯虚函数没有具体的实现,所以不能利用它来生成对象,但可以定义一个指向该类的指针,如程序中的C行。
定义一个纯虚函数,本质上是将一个空指针值0赋给函数名,但该函数的原型必须确定,纯虚函数不同于空函数,空函数有一个空的函数体,虽然它什么都不做,但是它是一个完整的函数,可以调用它。
程序中派生类B的成员void fun(int)是类A中纯虚函数的实现,它的函数原型必须与上述纯虚函数相同。
主函数中定义了一个指向基类的指针,然后根据赋值兼容性规则将其指向派生类的对象,在通过它调用了B类中的函数fun,这是运行是的多态性。虽然p指向了派生类的对象,但其形式上还是指向类A的,所以在类A中如果没有相应函数的说明,则程序中D行编译时会出错,只有在运行时才能确定其指向的是对象b1。所以A中的函数fun从语法上将是必须的,但从功能上将又不是必不可少的,没有必要定义其函数的实现,因而将其定义为串虚函数。
(一)

#include<iostream.h>
class A{
int a,b;
public:
int sum(int x,int y)
{return (x+y);}
};
class B:public A{
public:
int sum(int x,int y)
{return (x*y);}
};
void main()
{
A a1,*p;
B b1;
p=&a1;
cout<<p->sum(3,2)<<'\n';
p=&b1;
cout<<p->sum(3,2)<<'\n';
cout<<a1.sum(3,2)<<'\n';
cout<<b1.sum(3,2)<<'\n';
}

运行结果: 5 5 5 6
(二)

#include<iostream.h>
class A{
int a,b;
public:
virtual int sum(int x,int y)
{return (x+y);}
};
class B:public A{
public:
int sum(int x,int y)
{return (x*y);}
};
void main()
{
A a1,*p;
B b1;
p=&a1;
cout<<p->sum(3,2)<<'\n';
p=&b1;
cout<<p->sum(3,2)<<'\n';
cout<<a1.sum(3,2)<<'\n';
cout<<b1.sum(3,2)<<'\n';
}

运行结果: 5 6 5 6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值