C++ 继承与多态


转载地址:http://blog.sina.com.cn/s/blog_704a942e0101iex6.html

继承,就是新的类从已有类那里得到已有的属性和服务。从另一个角度来看,从已有类产生新类的过程就是类的派生。已有的类称为基类或父类,产生的新类称为派生类或子类。派生类同样也可以作为基类再派生新的类,这样就形成了类的层次结构。 

如下图是一个简单的继承的层次关系图。C++ <wbr>继承与多态

从下图,可以看出基类与派生类之间的关系。C++ <wbr>继承与多态


单继承

单继承是从现有的一个基类创建一个新类的过程。在C++中,定义单继承派生类的一般语法格式为:

class 派生类名:[public/private/protected] 基类名

{

  <派生类数据成员和函数成员定义>

 

}

公有(public)继承 :

 

       公有继承的特点是除基类的私有成员将继续为基类的私有成员外,基类的公有成员和保护成员将分别成为派生类的公有成员和保护成员,即派生类将共享基类中的公有成员和保护成员。

当类的继承方式为公有继承时,访问符合以下规则:

1)基类的publicprotected成员的访问属性在派生类中保持不变,在派生类中基类的private成员不可访问。

2)派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能访问基类的private成员。

 

3)通过派生类的对象只能访问基类的public成员。

私有继承

私有继承的特点是除基类的私有成员将继续为派生类的私有成员外,基类中的公有成员和保护成员将成为派生类的私有成员。

当类的继承方式为私有继承时,符合以下规则:

1)基类的publicprotected成员都以private身份出现在派生类中,但基类的private成员不可访问。

2)派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能访问基类的private成员。

 

3)通过派生类的对象不能访问基类中的任何成员。

保护继承(protected):

保护继承的特点是除基类的私有成员将继续为派生类的私有成员外,基类中的公有成员和保护成员将成为派生类的保护成员。当类的继承方式为保护继承时,符合以下规则:

1)基类的publicprotected成员都以protected身份出现在派生类中,但基类的private成员不可访问。

2)派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能访问基类的private成员。

 

3)通过派生类的对象不能访问基类中的任何成员

派生类的构造函数和析构函数

通常情况下派生类构造函数和析构函数的执行顺序,分两种情况:

1.派生类中不含对象成员

    构造函数的执行顺序是:先执行基类的构造函数,再执行派生类的构造函数;析构函数的执行顺序是:先执行派生类的析构函数,再执行基类的析构函数。

派生类不含对象成员时构造函数的格式:

派生类构造函数名(参数表):基类构造函数名(参数表)

{

//新增成员初始化语句;

 

}

2.派生类中含对象成员

    构造函数的执行顺序是:首先执行基类的构造函数,再执行对象成员的构造函数,最后执行派生类的构造函数;析构函数的执行顺序与构造函数的调用顺序正好相反。当派生类对象被删除时,派生类的析构函数被自动调用执行,由于析构函数也不能被继承,因此,系统在自动调用执行了派生类的析构函数后,还将自动调用执行基类的析构函数。

派生类中含有对象成员时构造函数的格式:

派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名1(参数表),……对象成员名n(参数表)

{

//新增数据初始化语句(不包括对象成员);

 

}

说明:

    (1)若基类使用缺省构造函数或不带参数的构造函数,则在派生类中定义构造函数时可略去“:基类构造函数名(参数表)”;此时若派生类也不需要构造函数,则可不定义构造函数。

    (2)如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯。

 

    (3)由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关,所以基类的析构函数不会因派生类没有析构函数而得不到执行,它们各自是独立的。

多继承C++中,定义多继承派生类的一般语法格式为:

class 派生类名:派生方式 基类名1,派生方式 基类名2……

{

//派生类新增的数据成员和函数成员

}

冒号后面是基类表,各基类之间用逗号分隔。

继承的语法如下:

class Teacher

{ };

class Student

{ };

class Teach_Assistant: public Teacher, public Student

{

  ...

 

}

多继承中派生类构造函数的格式:

派生类构造函数名(参数表):基类1构造函数名(参数表),……基类n构造函数名(参数表)

{

//新增数据初始化语句(不包括对象成员);

 

}

虚基类

多继承是从多个基类创建新类的过程,多继承层次结构可能很复杂,而且可能会导致派生类从同一基类中继承多次。例如,对于例10.12中,Son类派生自Father类和Mother类,而Father类和Mother类有一个公共基类Person类,如下图所示。

C++中,为了避免出现基类的两个副本,则可将基类说明为虚基类。从类派生新类时,使用关键字virtual将类说明为虚基类。

在例10.12中只要将基类重新定义为虚基类就能解决二义性问题,如:

class Father: virtual public Person

  };

class Mother: virtual public Person

  };

多态性的概念
多态性是指用同样的接口访问不同的函数。通俗地说,多态性是指用一个相同的名字定义不同的函数,这些函数的执行过程不同,但是有相似的操作。

面向对象的多态性从实现的角度来讲,可以分为静态多态性和动态多态性两种。

虚函数 

虚函数的定义方法是,在定义类时在其成员函数的前面加上关键字virtual,即

class  类名称

{

//类的其他成员

virtual  函数类型  函数名(参数序列)   //把此函数说明为虚函数

 

};

当函数说明为虚函数后,在定义该函数的代码前不用加关键字virtual,如

class  base

{

int  i;

public :

virtual void show()   //虚函数说明

};

//虚函数的定义

void show()

{

cout<<"i="<<i<<endl;

}

 

当类的成员函数被定义为虚函数后,凡以该类为基类的派生类中所有与该函数定义完全相同的函数,无论其前面是否有关键字virtual,编译器均将它们视为虚函数。

注意:

1)只有类的成员函数才能定义为虚函数,而不能是友元函数,也不能是静态成员函数。因为虚函数调用要靠特定的对象来决定该激活哪个函数。

2)派生类中,与基类中的虚函数同名的函数,不论是否有虚函数的说明,一律视为虚函数。但在容易引起混乱的情况下,最好在对派生类的虚函数进行重新定义时也加上关键字virtual

3)虚函数被重新定义时,其函数的原型与基类中的函数原型必须完全相同。

4virtual 只用来说明类声明中的原型,不能用在函数实现时。

5)本质:不是重载声明而是覆盖。

6)调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。

虚函数和成员函数重载的区别主要体现在以下几方面:

1)重载函数要求其函数的参数或参数类型必须有所不同,函数的返回类型也可以不同。但是,当重载一个虚函数时,也就是说在派生类中重新定义虚函数时,要求函数名、返回类型、参数个数、参数的类型和顺序与基类中的虚函数原型完全相同。如果仅仅返回类型不同,其余均相同,系统会给出错误信息;若仅仅函数名相同,而参数的个数、类型或顺序不同,系统将它作为普通的函数重载,这时虚函数的特性会丢失。

2)重载函数可以是成员函数或友元函数,而虚函数只能是成员函数。

3)重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据;而虚函数是根据对象的不同去调用不同类的虚函数的。

4)重载函数在编译时表现多态性,而虚函数在运行时表现出多态性。

纯虚函数与抽象类

纯虚函数的定义方法为:

    virtual  函数类型  函数名称(参数序列)=0;

即将普通虚函数设置为0。声明为纯虚函数之后,基类中就不再给出函数的实现部分。纯虚函数的函数体由派生类给出。

例如:

class  Obj

{

public:

virtual  void  Disp()=0;

 

};

抽象类

     一个类可以有多个纯虚函数,包含有纯虚函数的类称为抽象类。抽象类的作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。

     一个抽象类只能作为基类来派生子类。对于抽象类来说,不能说明抽象类的对象,但可以定义一个指向它的指针。这样,就可以间接处理抽象类,或通过该指针调用其派生类中的虚函数。如:

class A {          //A为抽象类

public:

virtual void show()=0;   / 纯虚函数作为类A的抽象类

 }

 object;  //错误,因A为抽象类,不能说明抽象类的对象

 *p;              //正确,可以声明指向抽象类的指针 

多态性的异质单向链

其要点是:先为异质链表上各被链对象建立一个公共基类,即把链表上的各个不同类型的对象统一成一种类型,并在此基类中定义有关的虚函数,然后构造含有统一的对象指针类型转换形式的函数调用界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值