c++的继承性就是指子类(派生类)继承父类(基类)。以下为例:
Person类
Person.h
#ifndef PERSON_H
#define PERSON_H
#include<string>
using namespace std;
class Person
{
public: //类内不写关键字,默认是private成员
Person();
void eat();
virtual~Person();//virtual关键字只用在.h中写就可以了。而且是被继承的,父类是虚的,子类不加virtual也会默认为是虚的,但为清楚保险,都加上virtual
private:
string m_sName;
protected:
int m_iAge;
};
#endif
Person.cpp
#include<iostream>
#include"Person.h"
using namespace std;
Person::Person()
{
cout << "Person()" << endl;
}
void Person::eat()
{
cout << "Person::eat()" << endl;
}
Person::~Person()
{
cout << "~Person()" << endl;
}
Worker.h
#ifndef WORKER_H//为了防止重复编译,在.h文件中采用这样的宏命令
#define WORKER_H
#include"Person.h"
class Worker:Person//不加关键字就默认是私有继承
{
public:
void work();
Worker();
int m_iSalary;
~Worker();
};
#endif
Worker.cpp
#include<iostream>
#include"Worker.h"
using namespace std;
Worker::Worker()
{
cout << "Worker()" << endl;
}
void Worker::work()
{
cout << "Worker::work()" << endl;
//m_sName = "zxb";//子类不可访问父类的私有成员
eat();//可以访问从父类的公有成员继承来的私有成员
m_iAge ++; //可以访问从父类的保护成员继承来的私有成员(实质是把父类的公有和保护成员都继承过来成了子类私有成员,这就是has a的关系,子类有父类的成员)
m_iSalary = 9;
}
Worker::~Worker()
{
cout << "~Worker()" << endl;
}
Soldier.h
#ifndef SOLDIER_H
#define SOLDIER_H
#include"Person.h"
class Soldier:protected Person//保护继承
{
public:
void work();
Soldier();
~Soldier();
private:
int m_iBonus;
};
#endif
Soldier.cpp
#include<iostream>
#include"Soldier.h"
using namespace std;
void Soldier::work()
{
m_iBonus = 10;
m_iAge = 20;//父类保护成员可以被访问
//m_sName = "aa"; //父类的私有成员被继承到无法访问的位置
cout << "Soldier::work()" << endl;
}
Soldier::Soldier()
{
cout << "Soldier()" << endl;
}
Soldier::~Soldier()
{
cout << "~Soldier()" << endl;
}
Infantry.h
#ifndef INFANTRY_H
#define INFANTRY_H
#include"Soldier.h"
class Infantry:public Soldier//公有继承:将父类的公有成员和保护成员分别继承到自己的公有成员中,父类的私有成员继承到看不见的位置而且不可访问
{
public:
Infantry();
~Infantry();
void attack();
void work();
};
#endif
Infantry.cpp
#include<iostream>
#include"Infantry.h"
using namespace std;
Infantry::Infantry()
{
cout << "Infantry()" << endl;
}
Infantry::~Infantry()
{
cout << "~Infantry()" << endl;
}
void Infantry::attack()
{
Soldier::work();//继承了父类的公有成员
//m_iBonus = 20;//不能访问父类私有成员
m_iAge = 22;//继承了父类的保护成员(是从曾父类继承来的保护成员)
}
void Infantry::work()
{
cout << "Infantry::work()" << endl;
}
demo.cpp
#include<iostream>
#include<stdlib.h>
#include"Person.h"
#include"Worker.h"
#include"Infantry.h"
#include"Soldier.h"
using namespace std;
int main()
{
Worker w1;//私有继承
//w1.m_sName = "zxb";//父类私有成员在子类内部和类外均不可访问
//w1.m_iAge = 22;//从父类的保护成员继承成的私有成员不可在类外访问
w1.m_iSalary = 100000;//子类的公有成员可以在类外被访问
//w1.eat();//从父类的公有成员继承成的私有成员不可在类外访问
w1.work();//虽然Worker::work()函数定义里面包含了私有成员,但是work()是公有的啊!所以可以调用。这就是对私有成员或保护成员的间接访问方式
Soldier s1;//保护继承
//s1.eat();//从父类的公有成员继承成的保护成员不可在类外访问
//s1.m_iBonus = 7;//不可访问私有成员
s1.work();//可以访问公有成员
Infantry i1;//公有继承
i1.attack();//attack()里调用了从父类公有成员继承来的Soldier::work()
i1.work();//此时访问的是子类自己的公有成员work(),这就是子类的work()隐藏了从父类继承的Soldier::work()。
i1.Soldier::work();//此时访问的是继承来的公有成员
Soldier s2 = i1;//这样
//s2 = i1;//或这样都是可以的,因为步兵Infantry一定是Soldier,子类一定是父类的一种,是is a的关系。但是注意只是内容一样,实质是不一样的两块内存,地址也不同
//Infantry i2 = s1;//反过来就不行了
Soldier* p1 = &i1;//用指针也可以
p1->work();
system("pause");
return 0;
}
运行结果:
A.继承有公有继承、私有继承、保护继承:
三种方式中,“无法访问”不代表子类没有继承父类的私有成员,而是将父类的私有成员继承到了无法访问的位置,无法直接访问,但是可以通过继承的其他可以访问的成员间接访问。
B.继承有多重继承(如上例的Person->Worker->Soldier),有多继承(指一个子类继承了多个父类;一般不太好用)。
C.子类和父类的两种关系:1.has a 指子类 有 父类的所有成员2.is a 指子类 是 一种父类。
D.继承里的隐藏关系:子类和父类的成员会存在隐藏关系,比如程序里的父类Soldier::work()和子类Infantry::work(),子类Infantry里既有自己的work()也有继承来的父类的work()而且都是公有成员。如程序里的i1,直接调用work()时,会调用到自己的work(),而父类的work()就好像被子类自己的work()隐藏起来了似的,如果要调用父类的work(),就要写明是Soldier::work()。
E.虚函数、多态和覆盖关系的必要性:如程序里的p1,虽然指向了i1,但是调用work()时,依旧调用到了自己(父类)的work(),因为p1的类型是父类指针Soldier*,所以直接调用肯定会调用到父类的函数,不可能调用到子类的函数。那有什么办法可以让p1调用work()时调用到子类对象i1的work()吗?这就需要用到虚函数、多态,涉及覆盖的关系了。