C++ 单继承简单练习 实现数组栈和链栈(类模板)

本文介绍了C++中的继承概念,包括子类、父类、派生等,并探讨了继承的三种方式及其访问权限。通过实例展示了如何使用继承创建数组栈和链栈,详细讲解了构造函数的使用以及子类如何调用父类构造函数。此外,还提供了测试代码以验证数组栈和链栈的正确实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++继承

继承,顾名思义,就是一个类(Child)是另一个类(Parent)的孩子,Child 获得了 Parent 的属性和方法。继承表现的是类在垂直方向上的关系。Child 叫子类,Parent 叫父类。一般子类中有的而父类中没有的继承又叫派生。继承的实质就是 父类的属性在子类中也存在一份。

需要注意的是:构造函数不能被继承

继承的基本语法:

class 子类名 : 继承方式 父类名
{
public:
    ...
protected:
    ...
private:
    ...
};

继承方式就是权限限定词:

class 子类名 : public 父类名    // 公有继承 

class 子类名 : protected 父类名    // 保护继承 

class 子类名 : private 父类名    // 私有继承 

其中公有继承方式一般用的最多。

不同的继承方式,子类中继承下来的属性的访问权限也会不同:

publicprotectedprivate
public继承publicprotected不可访问
protected继承protectedprotected不可访问
private继承privateprivate不可访问

表格第一列是继承方式,第一行是父类属性的访问权限,后面的是这些属性在子类中的访问权限。可以看到不管是什么继承方式,父类的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;
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值