i,好久不见,我是云边有个稻草人,偶尔中二的C++领域博主与你分享专业知识!U·ェ·U

图片

正文开始——

一、this指针

Date类中有Init和Print两个成员方法,函数体中没有关于不同对象的区分,那么d1调用Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?C++给出了隐含的this指针来解决这个问题。

  • 编译器编译后,类的成员函数默认都会在形参的第一个位置,增加一个当前类类型的指针,叫做 this指针。如Date类的 Init 的真实原型为:void Init(Date* const this,int year,int month,int day)

  • 类的成员函数中访问成员变量,本质都是通过 this指针 访问的,如 Init函数 中给_year赋值,this->_year=year。

  • C++规定不能在实参和形参的位置显示着写 this指针(编译时编译器会处理),但是可以在函数体内显示使用 this 指针。

#include<iostream>using namespace std;
//编译器自己会加上this,我们不必加上class Date{public:        //void Init(Date* const this, int year, int month, int day)        void Init(int year, int month, int day)	{              //this->_year = year;		_year = year;		_month = month;		_day = day;	}        //void Print(Date* const this)        void Print()	{        //this = nullptr;this不能被修改,但是this指向的内容可以被修改		cout << this->_year << '/' << _month << '/' << _day << endl;	}private://声明        int _year;        int _month;        int _day;};
//定义int year;
int main(){	Date d1;	Date d2;
        //d1.Init(&d1,2024,9,20)	d1.Init(2024, 9, 20);
        //d2.Init(&d2,2024,9,22)	d2.Init(2024, 9, 22);
        //d1.Print(&d1);	d1.Print();
        //d2.Print(&d2);	d2.Print();
        return 0;}

 习题三道

1.下⾯程序编译运⾏结果是(C)

A、编译报错 B、运⾏崩溃 C、正常运⾏

#include<iostream>using namespace std;
class Apublic:    void Print()    {        cout << "A::Print()" << endl;    }private:    int _a;}
int main(){    A* p = nullptr;    p->Print();
    return 0;}

2.下⾯程序编译运⾏结果是(B)

A、编译报错 B、运⾏崩溃 C、正常运⾏

#include<iostream>using namespace std;
class Apublic:    void Print()    {        cout << "A::Print()" << endl;        cout << _a << endl;    }private:    int _a;};
int main(){    A* p = nullptr;    p->Print();
    return 0;}

【分析】

下面的p->Print就相当于call Print函数的地址,虽然有指针解引用的形态但这不是真正的解引用。

图片

图片

3. this指针存在内存哪个区域的 (A)

A. 栈 B.堆 C.静态区 D.常量区 E.对象里面

this是一个隐含的形参。局部变量,形参存在函数栈帧里面。


二、C++和C语言实现Stack对比

面向对象三大特性:封装、继承、多态,下面我们来初步了解一下封装。

  • C++中数据和函数都放在了类里面,通过访问限定符进行了限制,不能再随意通过对象进行修改数据,这是C++封装的一种体现,这个是最重要的变化,这里的封装的本质是一种更严格规范的管理,避免出现乱访问修改的问题。封装不仅仅是这样,后面需要我们不断地学习。

  • C++中有一些相对方便的语法,比如:Init给的缺省参数会方便很多,成员函数每次不需要传对象地址,因为this指针隐含的传递了,方便了很多,使用类型不再需要typedef直接用类名就很方便。

  • 后面我们用STL中的适配器实现的Stack可以感受下C++的魅力。

【C实现Stack】 

C实现Stack
#include<stdio.h>#include<assert.h>#include<stdbool.h>#include<stdlib.h>
typedef int STDataType;typedef struct Stack{	STDataType* a;        int top;        int capacity;}ST;
void STInit(ST* ps){	ps->a = NULL;	ps->top = ps->capacity = 0;}
void STDestroy(ST* ps){        assert(ps);
        free(ps->a);	ps->a = NULL;	ps->top = ps->capacity = 0;}
void STPush(ST* ps, int x){        assert(ps);
        //判断空间是否充足        if (ps->top == ps->capacity)	{            int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;	    STDataType* tmp = (STDataType*)realloc(ps->a, newCapacity * sizeof(int));            if (tmp == NULL)	    {                perror("realloc file!");                return;	    }	    ps->a = tmp;	    ps->capacity = newCapacity;	}
	ps->a[ps->top++] = x;}
bool STEmpty(ST* ps){        assert(ps);        return ps->top == 0;}
void STPop(ST* ps){        assert(ps);        assert(!STEmpty(ps));
	ps->top--;}
STDataType STTop(ST* ps){        assert(ps);        assert(!STEmpty(ps));
        return ps->a[ps->top - 1];}
int main(){	ST s;        STInit(&s);
        STPush(&s, 1);        STPush(&s, 2);        STPush(&s, 3);        STPush(&s, 4);
        while (!STEmpty(&s))	{            printf("%d ", STTop(&s));            STPop(&s);	}
        STDestroy(&s);
        return 0;}

【C++实现Stack】 来都来了,不得敲一下

图片

C++实现Stack
#include<iostream>#include<assert.h>using namespace std;
class Stack{typedef int STDataType;public:        //成员函数        void Init(int n = 4)	{		_a = (STDataType*)malloc(sizeof(STDataType) * n);		_top = 0;		_capacity = n;	}
        void Push(STDataType x)	{            if (_top == _capacity)	    {                int newcapacity = _capacity * 2;		STDataType* tmp = (STDataType*)realloc(_a, newcapacity * sizeof(STDataType));                    if (tmp == NULL)		    {                        perror("realloc fail");                        return;		    }		    _a = tmp;		    _capacity = newcapacity;	    } 	        _a[_top++] = x;	}
        void Pop()	{            assert(_top > 0);	    _top--;	}
        bool Empty()	{            return _top == 0;        int Top()	{            assert(_top > 0);            return _a[_top - 1];
        void Destroy()	{                free(_a);		_a = nullptr;		_top = _capacity = 0;	}
//成员变量private:	STDataType* _a;        int _top;        int _capacity;};
int main(){	Stack s;	s.Init();	s.Push(1);	s.Push(2);	s.Push(3);	s.Push(4);
        while (!s.Empty())	{		cout<<s.Top<<" "; 		s.Pop();
	s.Destroy();
        return 0;}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐