栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

QT4 原生c++ 1.2 派生类、字符数组开辟空间与销毁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

QT4 原生c++ 1.2 派生类、字符数组开辟空间与销毁

1 面向对象中两个重要概念

1 派生类

派生类:利用继承机制,新的类可以从已有的类中派生。那些用于派生的类称为这些特别派生出的类的“基类”。

2 虚函数

虚函数可实现多态性 派生类只调用自己的函数。

下面来看示例:

class Stack{
public:
	virtual void push(char c) = 0; // 虚函数 基类只有定义
	virtual char pop() = 0;
};

基类只有原型的定义

class ArrayStack:public Stack{
	char* p;
	int maxSize;
	int top;
public:
	ArrayStack(int s)
	{
		top = 0;
		maxSize = s;
		//*****found*****1
		//p=_____;
		p = new char[s]; //为p申请s个char型空间
	}

	~ArrayStack()
	{
		//*****found*****2
		//_____;
		delete [] p; //释放指针 new的空间需要释放
	}

	void push(char c)
	{
		if(top == maxSize){
			cerr<<"Overflow!n";
			return;
		}
		//*****found*****3
		//_____;
		p[top] = c; //top为栈顶元素下标 添加的数据放到栈顶
		top++;
	}

	char pop()
	{
		if(top == 0){
			cerr<<"Underflow!n";
				return '';
		}
		top--;
		//*****found*****4
		//_____;
		return p[top];
	}

};

派生类中,对push函数做了具体的实现。

那么 ,到底何时调用基类的虚函数,何时调用派生类的虚函数呢。这里可以做一个实验。

#include 
#include 
using namespace std;

// 类定义
class A
{
public:
	virtual void print()
	{
		cout<<"这是基类A的print函数"<print();
    p2->print();
    return a.exec();
}

简单讲解一下,A是基类,B是派生类,print是虚函数。

先定义A类的实例aa,在定义B类的实例bb,然后定义基类指针p1和p2,再将aa和bb的地址赋予指针。这时候,p1输出的是A的函数,而p2输出的是B的函数。

虚函数的理论还是蛮绕的,就不误导观众了,这里最好找教材好好复习一下,这是个重要的知识点。

2 字符数组的开辟和销毁

字符数组是本次学习的重点。

先来看下代码:

#include 
#include 
using namespace std;

// 类定义
class Stack{
public:
	virtual void push(char c) = 0; // 虚函数可实现多态性 派生类只调用自己的函数
	virtual char pop() = 0;
};

class ArrayStack:public Stack{
char* p;
int maxSize;
int top;
public:
	ArrayStack(int s){
		top = 0;
		maxSize = s;
		p = new char[s]; //为p申请s个char型空间
	}

	~ArrayStack(){
		delete [] p;     //释放指针 new的空间需要释放
	}

	void push(char c){
		if(top == maxSize){
			cerr<<"Overflow!n";
			return;
		}
		p[top] = c; //top为栈顶元素下标 添加的数据放到栈顶
		top++;
	}

	char pop(){
		if(top == 0){
			cerr<<"Underflow!n";
				return '';
		}
		top--;
		return p[top];
	}

};


void f(Stack& sRef){
	char ch[] = {'a','b','c'};
	cout< 

输出结果为

先来分析下类结构:

基类Stack派生类ArrayStack
char* p;
int maxSize;
int top;
    virtual void push(char c) = 0; 
    virtual char pop() = 0;

ArrayStack(int s);

~ArrayStack();

void push(char c);

char pop();

基类实现了2个虚函数,1个是进栈push,1个是出栈pop。都是空的。

派生类实现了4个函数,分别是构造函数,析构函数,进栈push和出栈pop。

下面来看下main函数的逻辑

  1. 声明ArrayStack的对象as(10),这里要调用构造函数。
  2. 构造函数里,令top为0,maxSize为10,p开辟长度为10的字符数组变量
  3. 回到main,执行f函数,其形参是as。这里注意函数里是Stack类型,是基类。
  4. 在f函数里,as被传进来。声明了ch字符数组,其3个元素为a,b,c。首先cout这3个元素。控制台显示a,b,c。
  5. 对as执行push操作,进入push环节。这里也只能执行派生类的函数了。
  6. ch[0]是a,a进入push函数后,先做判断top == maxSize,这里目前是0==10所以否掉,执行p[top] = c;就是p[0]='a'。随后top自加变为1。
  7. 跳出push后,又来第2个push,变量是ch[1]就是b。继续。1==10不成立,所以p[1]='b' top=2。
  8. 再次push,这里判断2==3不成立,所以p[2]='c',top=3。
  9. 整理一下3次push的操作,ArrayStack对象as的p变量的前3个元素依次被赋予a,b,c三个字符。后面空着的8个元素还是空的。
  10. 下面执行pop操作。进入pop后,top=3,3==0不成立,跳过if,top变2,p[2]被返回,就是c。之后cout就是打印c
  11. 继续pop,top=2,2==0不成立,跳过if,top变1,p[1]=b被返回cout打印。
  12. 继续pop,top=1,1==0不成立,跳过if,top=0,p[0]=a被返回打印。
  13. f函数被执行完毕。返回main函数
  14. 执行完毕。程序退出,开始执行析构函数。
  15. 销毁p空间。

分析上述过程,p数组其实占用内存空间是固定的10个。pop后,也没有销毁。只有在最后析构函数中才被销毁。

看来 使用char存储字符不是很方便,比如要执行字符串拼接等操作,可能还是需要string类型更好。

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005867.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号