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的函数。
虚函数的理论还是蛮绕的,就不误导观众了,这里最好找教材好好复习一下,这是个重要的知识点。
字符数组是本次学习的重点。
先来看下代码:
- #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函数的逻辑
分析上述过程,p数组其实占用内存空间是固定的10个。pop后,也没有销毁。只有在最后析构函数中才被销毁。
看来 使用char存储字符不是很方便,比如要执行字符串拼接等操作,可能还是需要string类型更好。