多态性也是面向对象程序设计方法的一个重要特征,它主要表现在函数调用时实现“一种接口,多种方法”。
<1>基类指针指向派生类对象
SonClass son=new SonClass();①
FatherClass father=new SonClass();②//创建子类,返回基类引用
这是一个IS-A模型,例如“麻雀:鸟”,在这个模型中当然能得出“麻雀是鸟”,但反过来“鸟是麻雀”显然是不对的,即SonClass son=new FatherClass ();是不正确的。
“new SonClass()”完成的是创建SonClass对象,分配内存空间和初始化操作,然后将这个对象的引用通过“=”赋给father变量,也就是建立father变量与SonClass对象之间的关联。
应用类型的区别决定了不同的对象在方法表中不同的访问权限。①中的son对象和②中的father对象在内存布局上是一样的,差别就在于其引用指针的类型不同:father为FatherClass类型指针,而son为SonClass类型指针。其区别如下左图所示。
//basePtr.cpp : 测试基类对派生类的引用
#include "stdafx.h"
#include<iostream>
using namespace std;
class A
{
private:
int a;//a
public:
void setA(int i){a=i;}
void showA(){cout<<a<<endl;}
};
class B:public A
{
private:
int b;//a,b
public:
void setB(int i){b=i;}
void showB(){cout<<b;}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a,*pa;//pa为基类对象指针
B b,*pb;//pb为派生类对象指针
pa=&b;//基类指针pa指向派生类对象b
pa->setA(100); pa->showA();
pb=(B*)pa;//将基类指针pa强制转换为派生类指针
pb->setB(200); pb->showB();
cin.get();
}
(1) 上述程序中若使用pa->setB()或pa->showB()是非法的。
(2) 如果把语句pa=&b;改为pb=&a;也将编译出错,因为违反了IS-A原则。
(3) 在C++中赋值a=b;是正确的;而A refA=new B();将提示出错
<2>虚函数
#include "stdafx.h"
#include<iostream>
using namespace std;
class A
{
public void show(){cout<<"A.Show()"<<endl;}
};
class B:public A
{
public void show(){cout<<"B.Show()"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
A *pa;//pa为基类对象指针
B b;//b为派生类对象
pa=&b;//基类指针pa指向派生类对象b
pa->show();//调用的是A.show();
b.show();//调用的是B.show();
cin.get();
}
在上面的代码中,基类pa虽然指向了派生类对象,但是对于同名show,还是调用基类A的成员函数show(),而非派生类对象b的show()。
如果想通过指向派生类对象的指针调用派生类中覆盖的成员函数,只有使用虚函数(virtual function)。
在一个类继承结构中,可以使用一个函数表示不同的功能,以实现多态性。在C++中是通过虚函数机制来实现这种类的行为的多态性。
在上例中只要public void show()改为public virtual void show(),则后面的pa->show();将调用的是B.show()。
评论