Ⅰ类与对象①

1.定义

#include <iostream>
using namespace std;

const int N = 100;
class CPPStack
{
private:                 //数据为私有
    char s[N]; //栈的内容保存在s中
    int tp;        //栈顶指示器,栈空为-1
public:              //成员函数放在类中,会很臃肿,但代码效率高
    void init();       //声明和定义分开,更清晰,一目了然
    bool isEmpty();
    bool isFull();
    void push(char c);
    char pop();
    char top();
};

void CPPStack::init()    //指明对象即可
{
    tp = -1;
}

bool CPPStack::isEmpty()
{
    return (tp==-1);
}

bool CPPStack::isFull()
{
    return (tp==(N-1));
}

void CPPStack::push(char c)
{
    tp++;
    s[tp] = c;
}

char CPPStack::pop()
{
    int oldtp = tp;
    tp--;
    return s[oldtp];
}

char CPPStack::top()
{
    return s[tp];
}

int main()
{
    char str[] = {"0123456789"};
    CPPStack s;

    cout << str << endl;
    s.init();

    int i = 0;
    while(str[i] && !s.isFull())
        s.push(str[i++]);
    while(!s.isEmpty())
        cout << s.pop();
    cout << endl;
}
C++栈(升级版)

1.1 从C结构体到C++新结构体

#include <iostream>
#include <cstring>
using namespace std;

struct StuNode    //C里不能有函数
{
    int ID;
    char name[32];
    char gender[8];
    int age;
};
//const使Set能够读取,却不改变其值
//Set在外面,要有指针才能接触到struct
void Set(struct StuNode *s, int id, const char *sn, const char *sg, int a)
{
    s->ID = id;
    strcpy(s->name, sn);    //赋值时麻烦
    strcpy(s->gender, sg);
    s->age = a;
}

void Output(struct StuNode s)
{
    cout << s.ID << "," << s.name << "," << s.gender << "," << s.age << endl;
}

int main()
{
    struct StuNode myNode;  //定义有3个
    Set(&myNode, 101, "Tom", "male", 35);
    Output(myNode);
    return 0;
}
CStack
#include <iostream>
#include <string>
using namespace std;

struct StuNode    //可以拥有函数小可爱啦
{
    int ID;
    string name;
    string gender;
    int age;
    void Set(int id, const string &sn, const string &sg, int a)
    {
        ID = id;   //啧啧啧,看看人家这赋值,多方便
        name = sn;
        gender = sg;
        age = a;
    }
    void Output()
    {
        cout << ID << "," << name << "," << gender << "," << age << endl;
    }
};

int main()
{
    StuNode myNode;  //瘦身成功!

    myNode.Set(101, "Tom", "male", 35);
    myNode.Output();

    return 0;
}
CPPStack

1.2 从面向过程到面向对象

#include <iostream>
using namespace std;

const int N = 100;
struct CStack
{
    char s[N]; //栈的内容保存在s中
    int tp;        //栈顶指示器,栈空为-1
};

void init(CStack* stk)  //每个函数都要放到外面去
{
    stk->tp = -1;         //还要传递参数
}
        
bool isEmpty(CStack stk)  //要更改值的时候,用指针
{
    return (stk.tp==-1);   //不更改时,就用变量就好啦
}

bool isFull(CStack stk)
{
    return (stk.tp==(N-1));   
}

void push(CStack* stk, char c)
{
    stk->tp++;
    stk->s[stk->tp] = c;  //真的很麻烦欸
}

char pop(CStack* stk)
{
    int oldtp = stk->tp;
    stk->tp--;
    return (stk->s[oldtp]);
}

char top(CStack stk)
{
    return (stk.s[stk.tp]);
}

int main()
{
    char str[] = {"0123456789"};
    struct CStack s;

    cout << str << endl;
    init(&s);

    int i = 0;
    while(str[i] && !isFull(s))
        push(&s, str[i++]);
    while(!isEmpty(s))
        cout << pop(&s);
    cout << endl;
}
C栈
#include <iostream>
using namespace std;

const int N = 100;

struct CPPStack
{
    char s[N]; //栈的内容保存在s中
    int tp;        //栈顶指示器,栈空为-1
    void init()      //函数放到结构体里,就不用在每次的形参
    {                     中说自己的对象是谁了
        tp = -1;
    }
    bool isEmpty()
    {
        return (tp==-1);
    }
    bool isFull()
    {
        return (tp==(N-1));
    }
    void push(char c)
    {
        tp++;
        s[tp] = c;
    }
    char pop()
    {
        int oldtp = tp;
        tp--;
        return s[oldtp];
    }
    char top()
    {
        return s[tp];
    }
};

int main()
{
    char str[] = {"0123456789"};
    CPPStack s;

    cout << str << endl;
    s.init();      //使用函数的时候,要说明是谁的函数

    int i = 0;
    while(str[i] && !s.isFull())
        s.push(str[i++]);
    while(!s.isEmpty())
        cout << s.pop();
    cout << endl;
}
C++栈

1.3 类的定义

1.3.1 引入

树(类)有好多种,比如槐树、柳树、桂花树(对象),但这些树有一些共同的特征,比如都有树干树枝树叶、有纹理、有年龄(属性)都可以生长、随风飘摇(行为&操作)

   类(class)是具有相同属性和行为特征的一组对象的集合,是对他的对象的一种抽象描述

int a;中,int:数据类型,表示整数,不分配存储空间,a是变量,是整数中的一个,分配存储空间

  类是一种复杂的数据类型,可以用类类型定义一个对象: 对象

  消息:就是命令,让对象干什么事

 1.3.2 定义

 默认情况下,新结构体中的所有成员均是公有的而类中的所有成员均是私有的

1.4 对象的建立与使用

 

 1.5 成员的存取控制

 

 

 

 2.构造函数与析构函数

 

 之前设计的栈,由于空间是定好了的,你永远不知道会冒出来一个数据符不符合,所以我们可以动态地分配一下,当空间小的时候,就加个倍

 

#include <iostream>  //改变的地方用红色标记吧
using namespace std;

class CPPStackExt
{
private:
    char *s; //栈的内容保存在s中
    int tp;        //栈顶指示器,栈空为-1
    int size;  //增加了一个变量表示容量
public:
    void init();
    bool isEmpty();
    bool isFull();
    void push(char c);
    char pop();
    char top();
};


void CPPStackExt::init()
{
    tp = -1;
    size = 5;
    s = new char[size];
}

bool CPPStackExt::isEmpty()
{
    return (tp==-1);
}

bool CPPStackExt::isFull()
{
    return (tp==(size-1));
}

void CPPStackExt::push(char c)
{
    if (isFull())
    {
        char *p = new char[2*size];  //增加一个新指针,指向一个新区域
        for (int i=0; i<size; i++)    //把以前的先拷贝到新区域里
            p[i] = s[i];
        delete []s;   //删除以前的痕迹
        s = p;
        size = 2*size;   //扩成两倍
    }
    tp++;
    s[tp] = c;
}

char CPPStackExt::pop()
{
    int oldtp = tp;
    tp--;
    return s[oldtp];
}

char CPPStackExt::top()
{
    return s[tp];
}

int main(){

    CPPStackExt s;
    char str[]={"012345678"};

    cout << str << endl;    //此时输出0123456789
    s.init();

    int i=0;
    while(str[i])
        s.push(str[i++]);

    while(!s.isEmpty())
        cout<<s.pop();    //此时输出9876543210
    cout<<endl;

    return 0;
}

就像是倒水一样,5L的杯子里装满了水,但是现在变成10L水了,要先把5L倒出来,放到另一个10L的杯子里才行。

但是这样会出现问题,如果让你一直到10L水,你必须用更多的杯子来装水,这样会浪费大量的空间。这就跟所有的动态分配一样,用完之后要释放空间

//增加一个释放空间的函数
void CPPStackExt::release()
{
    if(s!=NULL)
   {
    delete []s;
    s = NULL;
    }
}

2.1 构造函数

 

#include <iostream>  //改变的地方用红色标记吧
using namespace std;

class CPPStackExt
{
private:
    char *s; //栈的内容保存在s中
    int tp;        //栈顶指示器,栈空为-1
    int size;  //增加了一个变量表示容量
public:
    CPPStackExt()            //构造函数①——无形参,用之前的
    {                               //  函数()时调用
       init();
       cout << "111" << endl;
    }
     CPPStackExt(int initSize)  //构造函数②——带默认形参,新写的
    {                                    //函数(3)时调用
       tp = -1;
       size = initSize;
       s = new char[size];
     cout << "222" << endl;
    }
    CPPStackExt(const CPPStackExt &scopy) //拷贝构造函数,新写的
    {                                //函数先()再(s)时调用
       tp = scopy.tp;
       size = scopy.size;
       s = scopy.s;
     cout << "333" << endl;
    }
    void init();   //不能没有啊,不然找不到
    bool isEmpty();
    bool isFull();
    void push(char c);
    char pop();
    char top();
};

void CPPStackExt::init()
{
    tp = -1;
    size = 5;
    s = new char[size];
}
bool CPPStackExt::isEmpty()
{
    return (tp==-1);
}
bool CPPStackExt::isFull()
{
    return (tp==(size-1));
}
void CPPStackExt::push(char c)
{
    if (isFull())
    {
        char *p = new char[2*size];  //增加一个新指针,指向一个新区域
        for (int i=0; i<size; i++)    //把以前的先拷贝到新区域里
            p[i] = s[i];
        delete []s;   //删除以前的痕迹
        s = p;
        size = 2*size;   //扩成两倍
    }
    tp++;
    s[tp] = c;
}
char CPPStackExt::pop()
{
    int oldtp = tp;
    tp--;
    return s[oldtp];
}
char CPPStackExt::top()
{
    return s[tp];
}

int main(){

    char str[]={"0123456789"};
    cout << str << endl;    //此时输出0123456789

 //   s.init();    //函数①自动调用,不需要了
    CPPStackExt s(3);
    int i=0;
    while(str[i])
        s.push(str[i++]);

    CPPStackExt s1(s);

    while(!s.isEmpty())
        cout<<s.pop();    //此时输出9876543210
    cout<<endl;
    return 0;
}

2.1.1 性质

①系统自动调用

②函数名与类名相同

③无返回值

④属于public共有的

⑤构造函数可以重载,名字可以一样

2.1.2 成员初始化列表

就是在{ }外面写  

类中若存在引用、const数据成员,不能使用赋值的显式初始化方式

 

2.2 析构函数

 

2.2.1 作用

对象消失时的清理工作(如释放内存单元)

2.2.2 性质

①没有返回值

②没有任何参数,不能重载

③在对象消失时由系统自动调用

 

 ~CPPStackExt()
    {
        release();
     cout << "析构" << endl; }

2.2.3 构造函数与析构函数的异同

 

posted @ 2020-04-13 11:56  ananasaa  阅读(203)  评论(0编辑  收藏  举报