1.继承的概念
继承主要是由于一些类存在包含关系,如定义了一个Person类
以及Worker类
,后者是前者的子集。在定义Worker类时与Person类重复的属性就不用再定义了。定义子集Worker类
时形式如下 。
实例化之后,内存中看,在Person类
中定义了名字和年龄,Worker类
中没有定义这两个,但由于继承了Person,其内存中也会存在名字和年龄,以及其特有的工资。
在示例化子类时(如Worker)时会先实例化其父类在实例化它自己,销毁时顺序是相反的。
2.继承方式
继承方式主要分为下图中的三种方式
(1)公有继承
公有继承在不同访问限定符下也是不同的
先看一下不同的访问限定符的作用
上图中由于m_iAge
和m_strName
分别在protected
和private
下,像右图那样调用是错误的。
而像这样在Person内可以调用函数对protected
和private
下的两个数据成员赋值,类外无法使用。(在不涉及继承时,protected
和private
没有区别)
①public访问限定符在公有继承中的特性
在使用的时候Worker
可以去调用父类Person
的数据成员以及成员函数。
②protected访问限定符在公有继承中的特性
父类的public
以及protected
下的成员函数和数据成员函数分别继承到了子类的public
及protected
下,而且子类自定义的成员函数也可定义父类protected
下的数据成员。
③private访问限定符在公有继承中的特性
父类的private
下的成员函数会被继承到子类private
下的不可见位置,像右图中那样调用m_iAge
是错误的。
总结一下这三种访问限定符继承特点如下
(2)保护继承
(3)私有继承
私有继承和上图中在Line
类private
下定义的对象成员一样,只能访问公有的数据成员以及成员函数。这两种都称为Has a
关系
Has a
子类只能访问父类公有的数据成员以及成员函数
3.代码例子
定义了一个Person
类
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
m_strName = "Merry";
}
void play()
{
cout << "Person--play()" << endl;
cout << m_strName << endl;
}
protected:
string m_strName;
};
从Person
类用保护继承定义了一个Soldier
类
#pragma once
#include "Person.h"
#include <iostream>
using namespace std;
class Soldier:protected Person //保护继承Soldier
{
public:
void work()
{
m_strName = "Jim"; //从Person继承来的数据成员
m_iAge = 20;
cout << m_strName << endl;
cout << m_iAge << endl;
cout << "Solider--work()" << endl;
}
protected:
int m_iAge;
};
(1)保护继承调用父类成员函数
在如下图中这样在主程序中会报错
因为play
是Soldier
保护继承父类的成员函数,属于在子类的protected
访问限定符下,无法被实例化调用。
但如果像这样把父类中的play
添加到子类中的函数中去,再调用work
时是可以显示出play
的内容的。
(2)保护继承再公有继承调用
再定义一个类Infantry
#pragma once
#include "Soldier.h"
class Infantry:public Soldier //从Soldier公有继承
{
public:
void attack()
{
m_strName = "Jim";
cout << m_strName << endl;
cout << "Infantry--attack()" << endl;
}
};
在主程序中调用如左图,其运行结果如右图。
(3)私有继承再公有继承调用
将Soldier
改为private
私有继承
#pragma once
#include "Person.h"
#include <iostream>
using namespace std;
class Soldier:private Person //私有继承Soldier
{
public:
void work()
{
m_strName = "Jim"; //从Person继承来的数据成员
m_iAge = 20;
cout << m_strName << endl;
cout << m_iAge << endl;
cout << "Solider--work()" << endl;
}
protected:
int m_iAge;
};
这时候再实例化Infantry
调用attack
函数就会报错
这是由于m_strName
从Person
父类私有继承到Soldier
子类的private
下,Soldier
可以调用其private
下的成员函数,但是Infantry
作为子类从父类Solder
公有继承时,是无法调用其private
下的数据成员的。
(但只要子类从父类派生,子类就含有父类所有的数据成员,只是有些无法调用)