看到“继承”这个词汇,我们首先想到的是清宫剧,皇帝:“看,放眼望去,都是朕打下的江山”。太子:“嘿嘿…嘿嘿嘿…嘿嘿嘿嘿(以后都是我的)”。其实在面向对象的程序中,继承即为在现有类(父类/基类)的基础上建立新类(子类/派生类),新类从已有类中获得属性和行为,并且允许新类扩展新的属性及行为,扩展新类的功能。
继承的目的:代码重用。
派生类定义格式:
class 派生类名称:继承方式 基类1,继承方式 基类2,...继承方式 基类n
{
派生类成员声明;
};
//其中,如果只有一个基类为单继承 有多个基类为多继承;
在使用类的继承时需要注意一下几点:
- 基类的构造函数、析构函数、赋值运算符重载函数,不能被子类继承(现在C++11新增了一种能够继承基类构造函数的机制)
- 子类不能选择性的继承父类的某些成员而舍弃其他成员,所以应该选择小而精的类作为基类。
- 派生类可以添加新成员,增加派生类功能,当新增的成员名与基类成员重复时,会隐藏基类的同名成员,执行派生类新生成员。
除上述注意事项以外,C++程序设计人员还应了解在使用类继承时,基类及派生类的构造函数及析构函数调用顺序:
当创建派生类对象时,首先会调用基类的构造函数完成从基类继承的数据成员的初始化,然后调用派生类构造函数完成派生类新增数据成员初始化。
当释放对象时,首先调用派生类析构函数然后调用基类析构函数。
派生类的设计一般包括三个步骤:
- 吸收继承成员;
- 改造基类成员:(1)通过继承方式(private、protected、public)改变基类成员在派生类中的访问权限;(2)在派生类中定义与基类中重名的新成员,隐藏基类中同名成员;
- 添加新成员。
#include<iostream>
#include <string>
using namespace std;
class Animal
{
private:
string name = "animal";
public:
// Animal(string Name = "Animal")
// {
// name = Name;
// }
void eat();
void breath();
void run();
};
void Animal::eat()
{
cout<<name<<" can eat"<<endl;
}
void Animal::breath()
{
cout<<name<<" can breath"<<endl;
}
void Animal::run()
{
cout<<name<<" can run"<<endl;
}
//子类
class Cat:public Animal
{
private:
string name = "cat";
public:
void catchMouse(); //派生新方法
};
void Cat::catchMouse()
{
cout<<name<<" can catch mouse"<<endl;
}
class Fish:public Animal
{
private:
string name = "fish";
public:
void swim();
};
void Fish::swim()
{
cout<<name<<" can swiming"<<endl;
}
int main()
{
cout<<"creat Animal a "<<endl;
Animal a;
a.breath();
a.eat();
a.run();
cout<<"creat cat b"<<endl;
Cat b;
b.breath();
b.catchMouse();
b.eat();
b.run();
cout<<"creat fish c"<<endl;
Fish c;
c.breath();
c.eat();
c.run();
c.swim();
return 0;
}
后记:
在C++中谈到继承,还有一种比较特殊的存在,既为虚继承:
所谓虚继承(virtual)就是子类中只有一份间接父类的数据。该技术用于解决多继承中的父类为非虚基类时出现的数据冗余问题,即菱形继承问题。关于虚继承的问题,后会详析。