面向对象程序设计精髓在于继承与多态,为了实现这两功能C++提供了一系列方法,本文介绍多态实现方法。
简单定义一个基类:
class Base{
public:
void fun(){
cout <<"This is Base\n";
}
int x;
};
声明两个派生类
class ClassA : public Base{
public:
void fun(){
cout <<"This is ClassA\n";
}
int a;
};
class ClassB : public Base{
public:
void fun(){
cout <<"This is ClassB\n";
}
int b;
};
void main()
{
ClassA a;
ClassB b;
Base *pa;
Base *pb;
pa=&a;
pb=&b;
pa->fun();
pb->fun();
}
主函数输出的是:
This is Base
This is Base
在基类Base没有声明虚函数情况下什么类型的指针就会调用什么类的函数,pa,和pb都是Base *型指针,只能调用派生类对象a,b中包含的基类的函数。
如果要实现多态性声明基类中函数时要加上virtual
class Base{
public:
virtual void fun(){
cout <<"This is Base\n";
}
int x;
};
当基类的fun声明为虚函数时,派生类相同的fun默认为虚函数,加没加virtual效果一样。
这样主函数输出为:
This is ClassA
This is ClassB
声明虚函数后基类指针会调用其指向派生类对象的函数,这样相同的调用产生不同的实现,从而实现多态。
进一步,需要将析构函数声明为虚函数,考察下面的代码:
Base *p=new ClassA();
delete p;
系统在销毁对象时只会调用基类Base的析构函数。将基类析构函数声明为虚函数后,销毁对象时会先调用派生类析构函数,然后调用基类析构函数,只要将基类的析构够函数声明为虚函数,所有的派生类析构函数将自动变为虚函数。
此外也可以在基类声明纯虚函数:
class Base{
public:
virtual void fun(){
cout <<"This is Base\n";
}
virtual int vfun() = 0;
int x;
};
一旦基类声明了纯虚函数,基类将变成纯虚类,不能产生对象,其派生类中必须要实现纯虚函数,哪怕是一个没有任何功能的空函数体,否则编译报错。
class ClassA : public Base{
public:
void fun(){
cout <<"This is ClassA\n";
}
virtual int vfun()
{
return 0;
}
int a;
};
小结:
1. 没有声明虚函数情况下根据指针类型判断调用哪个类对象的函数;
2. 声明了虚函数后根据指针所指对象类型判断调用哪个类对象的函数;
3. 虚函数在派生类中必须实现,哪怕是个空函数体;
4. 派生类地址可以父子给基类指针,但是基类地址不能赋值给派生类指针。