C++继承
■ 继承:在已有类的基础上创建新类的过程
面向对象程序设计中最重要的一个概念是继承。
当创建一个类时,不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。
一个 B 类继承A类,或称从类 A 派生类 B。 类 A 称为基类(父类),类 B 称为派生类(子类)
类继承关系的语法形式:
class 派生类名 : 基类名表
{
数据成员和成员函数声明
};
派生类可以访问基类中所有的非私有成员。
访问控制表示派生类对基类的继承方式,使用关键字:
public 公有继承
private 私有继承
protected 保护继承
不论种方式继承基类,派生类都不能直接使用基类的私有成员
因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
一般在基类成员想被派生类的成员函数访问情况下,在基类中声明为 protect。
一个派生类继承了所有的基类方法,但下列情况除外:
● 基类的构造函数、析构函数和拷贝构造函数。
● 基类的重载运算符。
● 基类的友元函数。
■ 继承类型
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型,通常使用 public 继承。
当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员,称为保护继承(protect)。
特别派生类定义了与基类同名的成员,在派生类中访问同名成员时屏蔽了基类的同名成员
在派生类中使用基类的同名成员,显式地使用类名限定符:
类名 :: 成员
例如:
class base
{ public :
int a , b ;
} ;
class derived : public base
{ public :
int b , c ;
} ;
void f ()
{derived d ;
d . a = 1 ;
d . base :: b = 2 ;
d . b = 3 ;
d . c = 4 ;
};
■ 多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:
class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
数据成员和成员函数声明
};
多继承方式下构造函数的执行顺序:
先执行所有基类的构造函数
再执行对象成员的构造函数
最后执行派生类的构造函数
其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。现在让我们一起看看下面的实例:
#include<iostream>
usingnamespace std;
classShape // 基类 Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
classPaintCost // 基类 PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};
classRectangle: public Shape, public PaintCost // 派生类
{
public:
int getArea()
{
return (width * height);
}
};
intmain(void)
{
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
cout << "Total area: "<< Rect.getArea() << endl; // 输出对象的面积
cout << "Total paint cost:$" << Rect.getCost(area) << endl; // 输出总花费
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Total area: 35
Total paint cost: $2450
■ 基类的初始化:
在创建派生类对象时用指定参数调用基类的构造函数来初始化派生类继承基类的数据
派生类构造函数声明为
派生类构造函数( 变元表) : 基类( 变元表) , 对象成员1( 变元表)
… 对象成员n ( 变元表 ) ;
构造函数执行顺序:基类 à 对象成员à 派生类
派生类构造函数和析构函数的定义规则:
1. 基类的构造函数和析构函数不能被继承
2. 如果基类没有定义构造函数或有无参的构造函数, 派生类也可以不用定义构造函数
3. 如果基类无无参的构造函数,派生类必须定义构造函数
4. 如果派生类的基类也是派生类,则每个派生类只负责直接基类的构造
5. 派生类是否定义析构函数与所属的基类无关
在C++中,派生类构造函数的一般格式为:
派生类::派生类名(参数总表):基类名(参数表)
{
// 派生类新增成员的初始化语句
}
■ 赋值兼容规则
赋值兼容规则指在程序中需要使用基类对象的任何地方,都可以用公有派生类的对象来替代。
例如:
声明两个类
class Base
{
…
};
classDerived:public Base
{
…
};
(1) 可以用派生类对象给基类对象赋值。例如:
Base b;
Derived d;
b=d;
这样赋值的效果是,对象b中所有数据成员都将具有对象d中对应数据成员的值。
(2) 可以用派生类对象来初始化基类的引用。例如:
Derived d;
Base &br=d;
(3) 可以把派生类对象的地址赋值给指向基类的指针。例如:
Derived d;
Base *bptr=&d;
这种形式的转换,是在实际应用程序中最常见到的。
(4) 可以把指向派生类对象的指针赋值给指向基类对象的指针。
例如:
Derived *dptr,obj; dptr=&obj;
Base *bptr=dptr;
在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员。
在赋值兼容时应注意:
(1) 声明为指向基类的指针可以指向它的公有派生类的对象,但不允许指向它的私有派生类的对象。
例如:
class B {…};
class D:privateB {…};
B b1,*pbl;D d1;
pb1=&b1; //合法,基类B的对象b1和B类的指针
pb1=&d1; //非法,不允许将基类指针指向它的私有派生类对象
(2) 允许将一个声明为指向基类的指针指向其公有派生类对象,但是不能将一个声明为指向派生类对象的指针指向其基 类的一个对象。
(3) 声明为指向基类对象的指针,当其指向公有派生类对象时,只能用它来直接访问派生类中从基类继承来的成员,而 不能直接访问公有派生类的定义的成员。
学习心得:面向对象的继承机制是非常重要的一个概念。类继承可以较方便地改变父类的实现,可以大大简化代码,减少重复,从而增强代码的可读性,使代码的逻辑更加清晰。但是父类通常会定义子类的部分功能和行为,所以改变父类可能就会影响到子类。所以我们在优化代码的时候可以将有包含关系的类与类之间用继承来实现代码的优化。