C++多态性和对象替换

C++多态性和对象替换

  派生类继承了基类除构造函数和析构函数外的所有数据成员和函数成员。派生类和基类存在一种特殊关系:派生类是一种基类,具有基类的所有功能。面向对象的程序设计利用派生类和基类之间的特殊关系,常常将派生类对象当作基类对象使用,或者用基类来代表派生类,其目的是提高代码可重用性。由于C++对数据类型一致性要求比较严格,一旦不能调用处理A类对象的函数afun(A x)来处理B类对象数据。

一、认识对象的替换和多态

通过一个例子更直观的理解对象的替换和多态:

class A
{
    public:
        void fun1() //普通函数成员fun1
        { cout<< "A::fun1 called
"; }
        virtual void fun2() //虚函数成员fun2
        { cout<< "Virtual A::fun2 called
"; }
};
class B:public A //定义派生类B,公有继承A
{
     public: 
        void fun1() //新增基类同名函数成员fun1
        { cout<< "B::fun1 called
"; }
        virtual void fun2() //新增基类同名虚函数成员fun2
        { cout<< "Virtual B::fun2 called
"; }
};
void exfun(A &x) //类外函数处理类对象
{
    cout<<"exfun call class A
";
    x.fun1();
}
void exfun1(A &x) //类外函数调用类虚函数,实现对象多态性
{
    cout<<"exfun call class A
";
    x.fun2();
}

  下面通过两个类分别定义对象和引用来观察它们所调用的函数是那些 

A aobj;B bobj; //分别定义两个类的对象
A &ra1=aobj;
A &ra2=bobj; //通过基类对象引用两个对象
ra1.fun1(); //显示 A::fun1 called
ra2.fun1(); //显示 A::fun1 called
ra1.fun2(); //显示 Virtual A::fun2 called
ra2.fun2(); //显示 Virtual B::fun2 called

  得到以下结论:

    1)通过基类ra2来引用派生类对象bobj,相当于将派生类对象当作基类对象来使用,这被称作对象替换

    2)通过基类引用调用虚函数成员fun2,基类对象aobj和派生类对象bobj会显示不同信息。换言之,接收相同指令fun2,基类对象和派生类对象表现出不同行为,呈现多样化形态,这就是对象的多态性

 二、类型兼容语法规则(对象替换)

  为了让派生类对象可以与基类对象一起共用算法代码,C++语言专门指定了如下的类型兼容语法规则

    1)派生类的对象可以赋值给基类对象。

    2)派生类的对象可以初始化基类引用,或者说基类引用可以引用派生类对象。

    3)派生类对象的地址可以赋值给基类指针,或者说基类的对象指针可指向派生类对象。

  应用类型兼容语法规则有一个前提条件和一个使用限制。

  前提条件:派生类必须共有继承基类。因为公有继承下,派生类拥有基类的全部功能,派生类对象可以当作基类对象使用。

  使用限制:通过基类的对象、引用或对象指针访问派生类对象时,只能访问到基类成员,赋值和访问时只能接收基类成员。

 示例:

A x1;B x2; A &x3 = x1; //定义类A,类B对象和类A的引用并初始化为类x1
x1 = x2; //派生类对象给基类对象赋值
x3 = x2; //基类引用可以引用派生类对象
A *p; p = &x2; //基类对象指针指向派生类对象
exfun(x2); //输出exfun call class A[换行] A::fun1 called
//此时通过类A的外部处理函数处理派生类B对象,完成代码重用

三、对象的多态性

  通过上面示例思考,如何通过基类引用或指针访问派生类中与基类中同名的函数?我们将调用对象的某个函数成员称为向对象发送一条消息。将执行函数成员完成某种程序功能称为对象响应该消息。不同对象接收相同消息,但会表现除不同的行为,这就是对象的多态性。对象多态性就是:调用不同对象的同名函数成员,所执行的函数不同,完成的程序功能也不同。导致对象多态性的同名函数有以下三种不同形式:

    1) 不同类之间的同名函数。类成员有作用域,不同类之间的函数成员可以同名互不干扰。

    2)类中的重载函数。通过一类中的函数成员可以重名,只要他们的形参个数不同或类型不同。重载函数成员导致的多态本质上属于重载函数多态。

    3)派生类中的同名覆盖。派生类中新增的函数成员可以与从基类继承来函数成员同名,但他们不是重载函数。

  引入对象多态性的目的是为了让另外一些处理基类的代码也能够被派生类对象重用。“另外一些”代码的作用也就是通过基类引用或对象指针访问派生类代码时可以根据实际引用或指向的对象类型,自动调用该类同名函数中新增成员。这是需要将这些同名函数声明成虚函数。C++语言以虚函数的语法形式来实现对象多态性,例如示例中的exfun1(A &x)函数。

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » C++多态性和对象替换