C++入门应该注意的问题(this指针和类对象)

先说说类

类有两种定义方式:

1. 声明和定义全部放在类中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

2. 声明放在.h文件中,类的定义放在.cpp文件中

类的访问和封装

问题:C++中struct和class的区别是什么?

解答:C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。 和class是定义类是一样的,区别是struct的成员默认访问方式是public,class是struct的成员默认访问方式 是private。

面向对象的三大特性:封装、继承、多态。

在类和对象阶段,我们只研究类的封装特性,那什么是封装呢?

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。 封装本质上是一种管理

类的实例化:

1. 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它

2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

3. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占 用物理空间

类对象模型

这里需要注意的是有两点比较重要

第一是计算类对象的大小

第二是类对象的存储方式

解决第一个问题,首先要清楚第二个问题:

一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。

接下来计算大小就根据结构体内存对齐的规则来计算,这里可以回想一下C语言内容中提出的几个问题:

1. 结构体怎么对齐? 为什么要进行内存对齐

2. 如何让结构体按照指定的对齐参数进行对齐

3. 如何知道结构体中某个成员相对于结构体起始位置的偏移量

4. 什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景

内存对齐:

C语言深度解析之六:自定义类型详解(结构体+枚举+联合)_何以过春秋的博客-CSDN博客

大小端:

C语言深度解析之一:数据存储_何以过春秋的博客-CSDN博客

this指针

说起this指针,其实就是从C++与C语言之间不同的语法特性出发的。

每一个对象都能通过 this 指针来访问自己的地址:this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。他的类型是* const

友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。

同时,静态成员函数也没有this指针。

为了引入this指针,我们看一个例子

class Date
{
public :
    void Display ()
    {
        cout <<_year<< "-" <<_month << "-"<< _day <<endl;
    }
    //void SetDate(Date* this,int year , int month , int day)
    void SetDate(int year , int month , int day)
    {
        _year = year;
        //this->_year = year;
        _month = month;
        //this->_month = month;
        _day = day;
        //this->_day = day;
    }
private :
    int _year ; // 年
    int _month ; // 月
    int _day ; // 日
};

int main()
{
    Date d1;
    Date d2;
    d1.Init(2021,10,8);
    //d1.Init(&d1,2021,10,8);
    
    d2.Init(2022,10,8);
    d1.Display();
    d2.Display();
    return 0;
}

Date类中有SetDate与Display两个成员函数,函数体中没有关于不同对象的区分,如果创建了d1,d2两个对象,那当d1调用SetDate函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

所以这里实际上有一个this指针,它指向当前对象,通过它可以访问当前对象的所有成员。

我们在调用成员函数后,编译器其实会再传一个参数进去,这个参数为当前对象的地址:

d1.Init(&d1,2021,10,8);

而成员函数本质上是这样:

void SetDate(Date* this,int year , int month , int day)
{
	this->_year = year;
    this->_month = month;
    this->_day = day;
}

解释完this指针后,来看下面这个程序:

class A
{
public:
    void show()
    {
        cout<<"show()"<<endl;
    }
    void Print()
    {
        cout<<_a<<endl;
    }

    void PrintA()
    {
        cout<<"PrintA()"<<endl;
    }
private:
    int _a;
};
int main()
{
    A* p = nullptr;
    p->show();
    p->Print();
    p->PrintA();
    return 0;
}

三次调用函数这个程序的结果是什么?

第一行第三行正常运行,第二场直接崩溃

这里还引出了一个面试问答:this指针可以为空吗?

最后谈一个问题:this指针存在哪里?

不是存在对象中哦

this指针是形参,形参和函数中的局部变量都是存在函数栈帧里面的,所以this指针是存在栈区的,vs下this指针是通过寄存器ecx传递的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

何以过春秋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值