当前位置:文档之家› 第7章 继承性和派生类

第7章 继承性和派生类

class派生类名:继承方式基类名
{
派生类新定义成员
};
public表示公有继承
继承方式private表示私有继承
protected表示保护继承
继承方式规定了如何访问从基类继承的成员。继承方式缺省,隐含私有继承。
多继承的定义格式如下:
class派生类名:继承方式1基类名1,
继承方式2基类名2,…
{
派生类新定义成员
例7.9
#include<iostream.h>
class A
{public:
A( ){a=0;}
A(int i){a=i;}
void Print( ) {cout<<a<<”,”;}
private:
int a;
};
class B:public A
{public:
B( ){b1=b2=0; } //隐式调用A的构造函数
解决的方法:
(1)成员名限定法来消除二义性,例如:
c1.A::f( );或者c1.B::f( );
7.2单继承
7.2.1成员访问权限的控制
例7.2
#include<iostream.h>
class A
{public:
void f(int i){cout<<i<<endl;}
void g( ){cout<<”g\n”;}
};
class B:A
{public:
void h( ){cout<<”h\n”;}
7.2.2派生类的构造和析构函数
派生类继承了基类的成员,实现了原有代码的重用,这只是一部分,而代码的扩充才是最主要的,只有通过添加新的成员,加入新的功能,类的派生才有实际意义。基类的构造函数和析构函数不能被继承。在派生类中,如果对派生类新增的成员进行初始化,就必须由程序员针对实际需要加入新的构造函数。与此同时,对所有从基类继承下来的成员的初始化工作,还是由基类的构造函数完成,我们必须在派生类中对基类的构造函数所需要的参数进行设置。
A::f;
};
void main( )
{B d1;
d1.f(6);
d1.g( );
d1.h( );
}
问题:
1.d1.g( );出现编译错。
2.去掉d1.g( );执行结果为:
6
h
3. A::f;将基类中的公有成员说明成派生类的公有成员。
4.将私有继承改为公有继承输出为:
6
g
h
例7.3
#include<iostream.h>
{public://新增公有成员Rectangle(float x,float y,float w,float h )
:Point(x,y)
{W=w;H=h;}
void 2( )
{cout<<W<<”,”<<H<<endl;}
private://新增私有数据成员
float W,H;
};
void main( )
在这个层次结构中,由上到下,是一个具体化、特殊化的过程;由下到上,是一个抽象化的过程。最高层抽象程度最高,从上到下加入了自己的新特征,而最下层是最为具体的。
在派生过程中,派生出来的新类也同样可以作为基类再继续派生新的类。直接参与派生出某类的基类称为直接基类。基类的基类称为间接基类,比如A类派生出B类,B类又派生出C类。则B类是C类的直接基类,A类是B类的直接基类。而A类可以称为C类的间接基类。
constructor B1.1
constructor B3.3
constructor A.4
1
2
4,3
说明:
1.派生类A的构造函数。
A(int i,int j,int k,int l):B1(i),B2(j),bb(k)
{a=l;
cout<<"constructor A."<<l<<endl;}
2.派生类构造函数的执行顺序。
取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表的各项顺序无关。
3.作用域运算符::的作用。
B1::print( );
B2::print( );
7.3.3二义性问题
第一种情形:
一般说来,在派生类中对基类成员的访问应该是唯一的,但是,由于多继承情况下,可能造成对基类中某成员的访问出现了不唯一的情况,则称为对基类成员访问的二义性问题。下面举一个简单的例子,对二义性问题进行深入讨论
{B d1;
B d2(5);
B d3(4,5,6);
d1.print( );
d2.print( );
d3.print( );
}
输出:
0,0,0
0,5,0
4,5,6
7.3多继承
7.3.1多继承的概念
多继承是指派生类具有多个基类。
多继承的定义格式如下:
class派生类名:继承方式1基类名1,
继承方式2基类名2,…
1.构造函数
派生类构造函数的一般形式为:
派生类名(派生类构造函数总叁数表)
:基类构造函数(参数表1),子对象名(参数表2)
{派生类中数据成员初始化}
派生类构造函数执行的一般次序如下:
1.基类构造函数。
2.子对象的构造函数。
3.派生类构造函数
例7.4公有继承
#include<iostream.h>
class Point//基类Point
5,5
20,10
2.析构函数
当对象被删除时,派生类的析构函数被调用。由于基类的析构函数也不能继承,因此在执行派生类的析构函数时,基类的析构函数也被调用。执行的顺序是先执行派生类的析构函数,再执行基类的析构函数。
3.派生类构造函数使用中注意的问题
派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有缺省构造函数或者根本没有定义构造函数。
新定义成员成员
派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。
2.私有继承(private)
私有成员只能在类中可见,不能再类外或派生类中使用。
特点:基类中的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类中不可访问。
private成员
{public:
B2(int i)
{b2=i;cout<<"constructor B2."<<i<<endl;}
void print( ) { cout<<b2<<endl;}
private:
int b2;
};
class B3//基类B3
{public:
B3(int i)
{b3=i;cout<<"constructor B3."<<i<<endl;}
private成员
Protected成员protected成员
public成员protected成员
private成员
protected成员
public成员
基类成员
派生类
新定义成员成员
派生类的成员函数可以访问基类中的公有成员和保护成员。
三种不同的继承方式的基类和派生类特性。
7.1.3基类与派生类的关系
int getb3( ) {return b3;}
private:
int b3;
};
class A: public B2, public B1//派生类A{ public:
A(int i,int j,int k,int l):B1(i),B2(j),bb(k)
{a=l;
cout<<"constructor A."<<l<<endl;}
{public:
Point(float xx=0,float yy=0){X=xx;Y=yy;}
void Move(float x,float y) {X+=x;Y+=y;}
void print1( )
{cout<<X<<”,”<<Y<<endl;}
private:
float X,Y;
};
class Rectangle: public Point//派生类
7.1基类和派生类
我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。
单继承多继承
7.1.1派生类的定义格式
单继承的定义格式:
void print( )
{B1::print( );
B2::print( );
cout<<a<<”,”<<bb.getb3( )<<endl;}
private:
int a;
B3 bb;
};
void main( )
{A aa(1,2,3,4);
aa.print( );
}
输出:
constructor B2.2
};
7.1.2派生类的三种继承方式
1.公有继承(public)
公有成员是类的接口,在类中和类外可见。
特点:基类的公有和保护成员的访问属性在派生类中不变、而基类的私有成员不可访问。
相关主题