理论知识:C++的this指针(类中的函数成员使用按引用传递时...)
目录
1.2非内联成员函数(non-inline member function)只会诞生一份函数实例
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;
- 第一个const:返回值是const 引用
- 第二个const:按照引用传递
- 第三个const:不会修改被隐形访问的对象
综上,该函数隐式地访问一个对象(即调用topval函数成员的类对象)
而显式地访问另一个变量(就是函数中按照引用传递的参数),返回一个const引用。
- 第一个const保护返回值,返回const引用,return后面的值如果是局部变量,内存泄漏!
- 第二个const保护显式调用的参数,即某个作为参数的类对象
- 第三个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;
}
..........