设为首页 加入收藏

TOP

C++多态性和对象替换(一)
2023-07-23 13:27:36 】 浏览:55
Tags:

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

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

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

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

 四、虚函数

  应用虚函数实现对象多态性的过程分为两步:先声明虚函数,在调用虚函数

1、声明虚函数

  在定义基类时使用关键字virtual将函数声明成虚函数,然后通过公有继承定义派生类,并重写虚函数成员,也就是新增一个与虚函数同名的函数成员。此后使用基类或派生类定义对象,其函数成员中只有虚函数成员才会在调用时呈现出多态性。

??为了更好的说明虚函数的声明和使用,我们编写一个简单示例代码如下:

class A //类声明
{
    public:
        virtual void fun1(); //声明虚函数成员fun1
        void fun2(); //声明非虚函数成员fun2
};
//类实现
void A::fun1() { cout<<"Base class A:virtual fun1() called"<<endl; }
void A::fun2() { cout<<"Base class A:non-virtual fun2() called"<<endl; }
class B:public A //定义派生类B,公有继承A
{
     public: 
       virtual void fun1(); //重写虚函数成员fun1
       void fun2(); //重写非虚函数成员fun2
};
void B::fun1() { cout<<"Derived class B:virtual fun1() called"<<endl; }
void B::fun2() { cout<<"Derived class B:non-virtual fun2() called"<<endl; }

??声明虚函数的语法细则:

????1)只能在类声明部分声明虚函数。在类

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇聊聊 C++ 中的几种智能指针 (下) 下一篇C++ 内存模型 write_x_read_y 试..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目