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 '\0';
		}
		top--;
		//*****found*****4
		//_____;
		return p[top];
	}

};

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

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

#include <QtCore/QCoreApplication>
#include <iostream>
using namespace std;

// 类定义
class A
{
public:
	virtual void print()
	{
		cout<<"这是基类A的print函数"<<endl;
	}
};

class B : public A
{
public:
	virtual void print()
	{
		cout<<"这是派生类B的print函数"<<endl;
	}
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
	// 定义2个对象
    A aa;
    B bb;
	// 赋值指针
    A *p1 = &aa;
    A *p2 = &bb;
	// 调用成员函数
    p1->print();
    p2->print();
    return a.exec();
}

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

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

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

2 字符数组的开辟和销毁

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

先来看下代码:

#include <QtCore/QCoreApplication>
#include <iostream>
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 '\0';
		}
		top--;
		return p[top];
	}

};


void f(Stack& sRef){
	char ch[] = {'a','b','c'};
	cout<<ch[0]<<","<<ch[1]<<","<<ch[2]<<endl;
	sRef.push(ch[0]); sRef.push(ch[1]); sRef.push(ch[2]);
	cout<<sRef.pop()<<",";
	cout<<sRef.pop()<<",";
	cout<<sRef.pop()<<endl;
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
	ArrayStack as(10);
	f(as);
    return a.exec();
}

输出结果为

先来分析下类结构:

基类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类型更好。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Intimes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值