转载地址:http://blog.sina.com.cn/s/blog_704a942e0101iex6.html
继承,就是新的类从已有类那里得到已有的属性和服务。从另一个角度来看,从已有类产生新类的过程就是类的派生。已有的类称为基类或父类,产生的新类称为派生类或子类。派生类同样也可以作为基类再派生新的类,这样就形成了类的层次结构。
单继承
单继承是从现有的一个基类创建一个新类的过程。在C++中,定义单继承派生类的一般语法格式为:
class 派生类名:[public/private/protected] 基类名
{
}
公有(public)继承 :
当类的继承方式为公有继承时,访问符合以下规则:
(1)基类的public和protected成员的访问属性在派生类中保持不变,在派生类中基类的private成员不可访问。
(2)派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。
(3)通过派生类的对象只能访问基类的public成员。
私有继承:
私有继承的特点是除基类的私有成员将继续为派生类的私有成员外,基类中的公有成员和保护成员将成为派生类的私有成员。
当类的继承方式为私有继承时,符合以下规则:
(1)基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可访问。
(2)派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。
(3)通过派生类的对象不能访问基类中的任何成员。
保护继承(protected):
保护继承的特点是除基类的私有成员将继续为派生类的私有成员外,基类中的公有成员和保护成员将成为派生类的保护成员。当类的继承方式为保护继承时,符合以下规则:
(1)基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可访问。
(2)派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。
(3)通过派生类的对象不能访问基类中的任何成员
派生类的构造函数和析构函数
通常情况下派生类构造函数和析构函数的执行顺序,分两种情况:
1.派生类中不含对象成员
派生类不含对象成员时构造函数的格式:
派生类构造函数名(参数表):基类构造函数名(参数表)
{
//新增成员初始化语句;
}
2.派生类中含对象成员
派生类中含有对象成员时构造函数的格式:
派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名1(参数表),……对象成员名n(参数表)
{
//新增数据初始化语句(不包括对象成员);
}
说明:
多继承在C++中,定义多继承派生类的一般语法格式为:
class 派生类名:派生方式1
{
//派生类新增的数据成员和函数成员
};
冒号后面是基类表,各基类之间用逗号分隔。
继承的语法如下:
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
{
int
public :
virtual void show();
};
//虚函数的定义
void show()
{
cout<<"i="<<i<<endl;
}
当类的成员函数被定义为虚函数后,凡以该类为基类的派生类中所有与该函数定义完全相同的函数,无论其前面是否有关键字virtual,编译器均将它们视为虚函数。
注意:
(1)只有类的成员函数才能定义为虚函数,而不能是友元函数,也不能是静态成员函数。因为虚函数调用要靠特定的对象来决定该激活哪个函数。
(2)派生类中,与基类中的虚函数同名的函数,不论是否有虚函数的说明,一律视为虚函数。但在容易引起混乱的情况下,最好在对派生类的虚函数进行重新定义时也加上关键字virtual。
(3)虚函数被重新定义时,其函数的原型与基类中的函数原型必须完全相同。
(4)virtual 只用来说明类声明中的原型,不能用在函数实现时。
(5)本质:不是重载声明而是覆盖。
(6)调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。
虚函数和成员函数重载的区别主要体现在以下几方面:
(1)重载函数要求其函数的参数或参数类型必须有所不同,函数的返回类型也可以不同。但是,当重载一个虚函数时,也就是说在派生类中重新定义虚函数时,要求函数名、返回类型、参数个数、参数的类型和顺序与基类中的虚函数原型完全相同。如果仅仅返回类型不同,其余均相同,系统会给出错误信息;若仅仅函数名相同,而参数的个数、类型或顺序不同,系统将它作为普通的函数重载,这时虚函数的特性会丢失。
(2)重载函数可以是成员函数或友元函数,而虚函数只能是成员函数。
(3)重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据;而虚函数是根据对象的不同去调用不同类的虚函数的。
(4)重载函数在编译时表现多态性,而虚函数在运行时表现出多态性。
纯虚函数与抽象类
纯虚函数的定义方法为:
即将普通虚函数设置为0。声明为纯虚函数之后,基类中就不再给出函数的实现部分。纯虚函数的函数体由派生类给出。
例如:
class
{
public:
virtual
};
抽象类
class A {
public:
virtual void show()=0;
A
A
多态性的异质单向链
其要点是:先为异质链表上各被链对象建立一个公共基类,即把链表上的各个不同类型的对象统一成一种类型,并在此基类中定义有关的虚函数,然后构造含有统一的对象指针类型转换形式的函数调用界面