C++ this指针(类中的函数成员使用按引用传递时...隐式和显式调用类对象)

本文围绕C++的this指针展开。首先指出类的成员变量(非静态)随对象分配空间,成员函数(非静态)储存在其他位置,非内联成员函数仅诞生一份实例。接着介绍this指针是隐含在对象成员函数内的指针,用于区分不同对象调用同一函数。最后通过实例说明this指针的应用及返回引用的相关问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理论知识:C++的this指针(类中的函数成员使用按引用传递时...)

 

目录

1问题的引出

1.1成员变量和成员函数储存在不一样的位置

 1.2非内联成员函数(non-inline member function)只会诞生一份函数实例

2this指针 

不包含this指针的成员函数 

3补充


 

1问题的引出

1.1成员变量和成员函数储存在不一样的位置

空类的大小是多少?

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QDebug>
namespace Ui {
class MainWindow;
}

void test01();


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

class Person
{
public:

private:
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    test01();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void test01()
{
    qDebug()<<"test01";
    qDebug()<<"sizeof(Person)"<<sizeof(Person);

}

空类的大小为:1byte

每个类中,都有独一无二的地址,char类型,所以空类也是有大小的。

class Person
{
public:
    int a;
    void func();

private:
};

对类稍作修改:

输出如下:

int类型的大小是4byte,但是没有计算func()函数的大小

所以可以判断,类的成员变量(非静态)是跟着对象一起分配空间的,成员函数(非静态)储存在其他位置

 


对类稍作修改,从输出也可以看出来

类的成员变量(非静态)是跟着对象一起分配空间的,成员函数(非静态)储存在其他位置

静态变量也好,静态成员变量也好,都不随着类的实例化(创建对象)而分配空间,静态本身就意味着在全局区开辟空间

class Person
{
public:
    int a;
    static int b;
    void func();
    static void static_func();

private:
};

但是也要注意对齐方式,对齐默认是8byte一组,int 是4byte,系统默认补上4byte,之后再算double的长度,所以加起来是16byte

class Person
{
public:
    int a;
    static int b;
    void func();
    static void static_func();
    double d_a;

private:
};

 

更改对齐方式:

#pragma pack(1)
class Person
{
public:
    int a;
    static int b;
    void func();
    static void static_func();
    double d_a;

private:
};

 1.2非内联成员函数(non-inline member function)只会诞生一份函数实例

那么问题来了,既然函数不跟着类的对象走(不在实例化中分配内存空间),在有多个对象时,访问同一个函数时,编译器如何区分?此时就需要this指针。

C++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inline member function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

                             

2this指针 

C++提供特殊的指针,解决以上问题,

C++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后。

它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址。

也就是说虽然我们没有写上this指针,编译器在编译的时候也会加上的。

因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果

this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,

在外部看来,每一个对象都拥有自己的函数成员。一般情况下,并不写this,而是让系统进行默认设置。

this指针永远指向当前对象。

成员函数通过this指针即可知道操作的是那个对象的数据。this指针是一种隐含指针

它隐含于每个类的非静态成员函数中。this指针无需定义,直接使用。

                               

编译器会自动添加this指针来区别。

this指针应用实例:

//h
class Person
{
public:
    Person();
    Person(const int for_a);
    ~Person();

    int a;


    void func_this(const Person & p);

private:
};
//cpp
Person::Person()
{
    qDebug()<<"进入Person构造函数";
}
Person::Person(const int for_a)
{
    this->a  = for_a;
    qDebug()<<"进入Person含参析构函数";
}
Person::~Person()
{
    qDebug()<<"进入析构函数";
}
void Person::func_this(const Person & p)
{
    if(this->a>p.a)
    {
        qDebug()<<"this大";
    }
    else if(this->a<p.a)
    {
        qDebug()<<"p大";
    }
    else
    {
        qDebug()<<"相等";
    }
}
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    test01();
    Person p1 = Person(1);
    Person p2 = Person(2);
    p1.func_this(p2);
    p2.func_this(p1);

}

输出结果: 

从显式初始化就可以看出,p1的a是大于p2的a的,使用p1.func_this的时候,this指向p1,反之p2调用的时候也是如此。

this是指针,永远指向调用对象本身

ClassName * const this = 调用接口的对象;

示例:

.h

class Plus
{
public:
    Plus();
    ~Plus();

    int item_one;

    void show();
};

.cpp

void Plus::show()
{
    qDebug()<<"(*this).item_one:"<<(*this).item_one;
    qDebug()<<"this->item_one:"<<this->item_one;
}
Plus p6;
p6.show();

 输出结果:

可以看出,this是指针,指向对象本身

                                         

不包含this指针的成员函数 

友元函数,被static修饰的成员函数

 

3补充

stock00.h//类声明
class Stock
{
private:
    std::string company;
    long shares;
    double share_cal;
    double total_cal;
public:
    Stock();
    Stock(const std::string & co,long n = 0,double pr = 0.0);
    ~Stock();
    void acquire(const std::string & co,long n,double pr);
    void buy(long num,double price);
    void sell(long num,double price);
    void update(double price);
}
#endif

在这个类中,如果我们现在需要查看两个对象的total_cal,并对比谁的更大。

那么问题来了,如果我们假设这个方法的命名为topval();

使用stock1.topval( )访问stock1的数据,使用stock2.topval( )访问stock2的数据 

现在需要将第二个对象作为参数传递才行,首选const Stock &,及按引用传递

那么,如何将对比后的内容返回呢?最简单的就是返回引用,该引用指向数值较大的变量所属的对象

用于比较的函数原型如下:

const Stock & topval (const Stock & s) const;
  1. 第一个const:返回值是const 引用
  2. 第二个const:按照引用传递 
  3. 第三个const:不会修改被隐形访问的对象

综上,该函数隐式地访问一个对象(即调用topval函数成员的类对象)

显式地访问另一个变量(就是函数中按照引用传递的参数),返回一个const引用。

  1. 第一个const保护返回值,返回const引用,return后面的值如果是局部变量,内存泄漏!
  2. 第二个const保护显式调用的参数,即某个作为参数的类对象
  3. 第三个const保护隐式调用的类对象,防止其被修改 常函数(不能对普通成员变量进行修改,可以被任意对象调用)
const Stock & topval (const Stock & s) const
{
    if(s.total_val > total_val )
      return s;
    else
      return ??????????;
}
如果大于,很简单,返回作为参数的引用即可。
但是如果小于,需要返回调用这个公告接口的对象,该如何书写呢?

上面出现的问题,就是需要返回this,每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象

如果需要引用整个调用对象,则可以使用表达式*this,在函数的括号后面使用const,就表示不能使用this来修改对象的值

主要,要返回的不是this,而是*this,this是指针,我们要返回的是指针指向的内存中的值。所以要使用*进行取值。 

完整代码如下:

//stock20.h
........//预处理头文件

class Stock
{
 private:
    ........
    double total_val;
    .......
public:
    Stock();
    Stock(const std::using & co,long n = 0,double pr = 0.0);
    ~Stock();
    ..........
    const Stock & topval(const Stock & s)const;
    ..........
}
//stock20.cpp
..........//源文件

Stock::Stock()
{
   .......
   total_vavol = 0.0;
   .......
}

Stock::Stock(const std::using & co,long n = 0,double pr = 0.0)
{
   ..........
}

Stock::~Stock()
{
   
}
..........
const Stock & Stock::topval(const Stock & s) const
{
   if(s.total_val > total_val )
      return s;
    else
      return *this;
}
..........

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值