C++继承
继承,顾名思义,就是一个类(Child)是另一个类(Parent)的孩子,Child 获得了 Parent 的属性和方法。继承表现的是类在垂直方向上的关系。Child 叫子类,Parent 叫父类。一般子类中有的而父类中没有的继承又叫派生。继承的实质就是 父类的属性在子类中也存在一份。
需要注意的是:构造函数不能被继承
继承的基本语法:
class 子类名 : 继承方式 父类名
{
public:
...
protected:
...
private:
...
};
继承方式就是权限限定词:
class 子类名 : public 父类名 // 公有继承
class 子类名 : protected 父类名 // 保护继承
class 子类名 : private 父类名 // 私有继承
其中公有继承方式一般用的最多。
不同的继承方式,子类中继承下来的属性的访问权限也会不同:
public | protected | private | |
public继承 | public | protected | 不可访问 |
protected继承 | protected | protected | 不可访问 |
private继承 | private | private | 不可访问 |
表格第一列是继承方式,第一行是父类属性的访问权限,后面的是这些属性在子类中的访问权限。可以看到不管是什么继承方式,父类的private属性在子类中都是无法访问的(跟现实生活挺像的,爸爸的私人物品,儿子是无法去访问的)。同时也能发现:继承方式只会增强父类的属性在子类当中的权限强度。
继承的构造函数写法
-
子类的构造函数必须要采用初始化参数列表的写法
-
子类构造函数必须调用父类构造函数初始化继承下来的属性,也就是父类属性只能通过父类的构造函数初始化
-
构造子类对象时候,必定先调用父类的构造函数
下面来简单实现一下数组栈和链栈:
关于栈的一些算法,这里不做解释,主要讲继承
想了一会儿,数组栈和链栈似乎只有一个相同的属性:当前栈的大小(size)。于是给父类来个保护属性:
// 栈的当前大小
int m_size;
再来个公有方法访问 m_size:
int size() const
{
return m_size;
}
好像太短了,那再来个判空方法:
bool isEmpty() const
{
return 0 == m_size;
}
父类 Stack
stack.hpp
#pragma once
#include <cstdio>
class Stack
{
public:
explicit Stack()
{
m_size = 0;
}
int size() const
{
return m_size;
}
bool isEmpty() const
{
return 0 == m_size;
}
protected:
int m_size;
};
下面数组栈(模板类),继承自 Stack类
因为是数组,需要有长度,即栈的容量,或最大大小:
int m_maxSize; // 数组栈的容量
_Ty* m_memory; // 存储数据的内存
int m_top; // 栈顶下标(栈空时为1)
子类 ArrayStack
arrayStack.hpp
#pragma once
#include "stack.hpp"
template <class _Ty>
class ArrayStack: public Stack
{
public:
explicit ArrayStack(int maxSize): Stack(), m_maxSize(maxSize)
{
m_memory = new _Ty[m_maxSize];
m_top = -1;
}
virtual ~ArrayStack()
{
delete[] m_memory;
}
int maxSize() const
{
return m_maxSize;
}
void push(_Ty ty)
{
if(m_size >= m_maxSize)
return;
m_memory[++m_top] = ty;
m_size++;
}
void pop()
{
if(isEmpty())
return;
m_top--;
m_size--;
}
_Ty top() const
{
if (isEmpty())
{
return NULL;
}
return m_memory[m_top];
}
protected:
int m_maxSize; // 数组栈的容量
_Ty* m_memory; // 存储数据的内存
int m_top; // 栈顶下标(栈空时为1)
};
下面链栈(模板类),继承自 Stack类
链栈并不需要容量限制,因为是用链表实现的
先来个节点类:
// 节点类
template <class _Ty>
struct Node
{
Node<_Ty>() : next(nullptr) { }
Node(_Ty data) : data(data), next(nullptr) { }
_Ty data;
Node<_Ty>* next;
};
在栈类中需要两个节点:头和尾,即 栈顶 和 栈底:
Node<_Ty>* m_bottom; // 栈底节点
Node<_Ty>* m_top; // 栈顶节点
子类 ListStack
listStack.hpp
#pragma once
#include "stack.hpp"
// 节点类
template <class _Ty>
struct Node
{
Node<_Ty>() : next(nullptr) { }
Node(_Ty data) : data(data), next(nullptr) { }
_Ty data;
Node<_Ty>* next;
};
template <class _Ty>
class ListStack: public Stack
{
public:
explicit ListStack(): Stack()
{
m_bottom = new Node<_Ty>;
m_top = m_bottom;
}
virtual ~ListStack()
{
Node<_Ty>* pMove = m_bottom->next;
while (pMove != nullptr)
{
Node<_Ty>* tmp = pMove;
pMove = pMove->next;
delete tmp;
}
delete m_bottom;
}
void push(_Ty ty)
{
Node<_Ty>* newNode = new Node<_Ty>(ty);
m_top->next = newNode;
m_top = newNode;
m_size++;
}
void pop()
{
if (isEmpty())
{
return;
}
Node<_Ty>* pMove = m_bottom;
while (pMove->next != m_top)
{
pMove = pMove->next;
}
m_top = pMove;
delete m_top->next;
m_size--;
}
_Ty top() const
{
if (isEmpty())
{
return NULL;
}
return m_top->data;
}
protected:
Node<_Ty>* m_bottom; // 栈底节点
Node<_Ty>* m_top; // 栈顶节点
};
测试代码:
#include "arrayStack.hpp"
#include "listStack.hpp"
#include <iostream>
#include <string>
using namespace std;
class Mm
{
public:
Mm(int age = 18, string name = "MM")
: m_age(age), m_name(name)
{}
int age() const
{
return m_age;
}
string name() const
{
return m_name;
}
// 重载一下 << 方便打印数据
friend ostream& operator<<(ostream& out, const Mm& mm)
{
out << "Name: " << mm.name() << " Age: " << mm.age();
return out;
}
protected:
int m_age;
string m_name;
};
// 测试数组栈
void testArrayStack()
{
ArrayStack<Mm>* mmArr = new ArrayStack<Mm>(10);
for(int i = 0; i < 10; i++)
{
mmArr->push(Mm(i, string("mm")));
}
cout << "testArrarStack: " << endl;
while(!mmArr->isEmpty())
{
cout << mmArr->top() << endl;
mmArr->pop();
}
cout << endl;
}
// 测试链栈
void testListStack()
{
ListStack<Mm>* mmList = new ListStack<Mm>;
for(int i = 0; i < 10; i++)
{
mmList->push(Mm(i, string("mm")));
}
cout << "testListStack: " << endl;
while(!mmList->isEmpty())
{
cout << mmList->top() << endl;
mmList->pop();
}
cout << endl;
}
int main(int argc, char** argv)
{
testArrayStack();
testListStack();
return 0;
}
运行结果: