C++:类、对象、this指针、内联函数


现实世界中的实体可以抽象出类别的概念。对应于计算机世界就有一个(class)的概念,因为类是一个抽象的概念的对应体,所以计算机不给它分配内存,只有当类实例化为对象时,给对象分配内存
在这里插入图片描述
类是设计的产物,对象是对类的实例化,设计类型时并没有给其开辟空间,实例化为对象后开空间,我们操作的是对象,而不是类

C++类的设计

C++中,类是一种数据类型,客观事物是复杂的,要描述它必须从多方面进行,也就是用不同的数据类型来描述不同的方面。类把数据(事物的属性)和函数(事物的行为、操作)封装为一个整体,如商场中的商品可以这样描述:

  • 商品名称(用字符串描述),该商品数量(用整数描述), 该商品单价(用浮点数描述),该商品总价(用浮点数描述)。
    class CGoods
    {
          
          
    public:
    	char Name[21];
    	int Amount;
    	float Price;
    	float Total_value;
    };//最后的分号不可少
    
  • 关键字class是数据类型说明符,指出下面说明的是类。标识符CGoods是商品这个类的类型名。花括号中是构成类体的一系列成员,关键字public是一种访问限定符

访问限定符有三种:private,protected、public,如果在类起始点无访问说明符号,系统默认为private

设计一个类的一般格式为:

class 类名
{
    
    
private:
	成员表1;
public:
	成员表2;
protected:
	成员表3;
};

成员函数的定义

函数定义通常在类的说明之后进行,其格式如下:

返回值类型  类名::函数名(参数表)
{
    
    
	//函数体
}

:: 称为作用域解析运算符,它指出该函数是属于那一个类的成员函数

对象(instance)


对象是类的实例。声明一种数据类型只是告诉编译系统该数据类型的构造,并没有预定内存。设计出来的类只是一个样板,以此样板可以在内存中开辟出同样结构的实例——对象。

创建类的对象可以有两种方法:

  1. 直接定义类的实例对象,创建在栈区:CGoods Car; int I;
  2. 动态创建类的对象,创建在堆区:CGoods *p = new CGoods();

有两种方法存储对象

第一种方法是为每一个对象都分配全套的内存来存属性和方法,包括安放成员数据的数据区和安放成员函数的代码区
在这里插入图片描述

但是区别同一个类的各个不同对象的属性是由数据成员决定的,不同对象的数据成员的内容是不一样的;而行为(操作)是用函数来描述的,这些操作的代码对所有的对象都是一样的,因而为每个对象都存储一份函数代码会造成空间上的浪费

第二种方法仅为每个对象分配一个数据区,代码区(放成员函数的区域)为各对象所共用
在这里插入图片描述
C++采用第二种方法存储对象。不同的对象有各自的属性,但是方法都是同一个方法,那么方法是怎么区别它操纵的到底是哪个对象的数据呢?这就是this指针的来源与用处所在

this指针


C++编译器对C++编译的时候,有三个步骤:

  1. 识别类里面的属性成员
  2. 识别方法,只识别方法的声明
  3. 改写类的方法(函数)成员

改写的具体有如下
对于如下方法:

void CGoods::RegisterGoods(char name[], int amount, float price)
{
    
    
	strcpy(Name, name);
	Amount = amount;
	Price = price;
}

编译器会改写为:

void CGoods::RegisterGoods(CGoods *const this, char name[],int amount,float price)
{
    
    
	strcpy(this->Name, name);
	this->Amount = amount;
	this->Price = price;
}

在类里面识别到的属性和类成员函数属性同名时,就会加上this指针,这是编译器编译时自动加的,我们也可以手动加,编译时系统就不给你加了

在主函数中调用类的成员函数时:

int main()
{
    
    
	CGoods x;
	CGoods y;
	x.RegisterGoods("C++",16,94);
	y.RegisterGoods("Java",10,88);
}

调用的那两句就等价于

RegisterGoods(&x,"C++",16,94);
RegisterGoods(&y,"Java",10,88);

这样,通过this指针就解决了上述的问题:“ 不同的对象有各自的属性,但是方法都是同一个方法,那么方法是怎么区别它操纵的到底是哪个对象的数据呢 ”

下面给出this指针的基本定义

this指针是类的一个自动生成、自动隐藏的私有成员,它存在于类的非静态成员函数中,指向被调用函数所在的对象。全局仅有一个this指针,当一个对象被创建时,this指针就存放指向对象数据的首地址。

每一个对象都隐式包含一个指针,指向对象自身。当对象调用成员函数时,会默认将对象自身传递给该函数,在函数体内不直接使用该对象名,而是使用this指针,即this指针指向该对象自身,即指向调用者

内联函数


直接在类内定义的函数或用inline关键字修饰的定义在类外的函数称为内联函数,内联函数在调用时直接拷贝一份过去,提高了效率,以空间换时间

如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方,因而对内联函数进行任何修改,都需要重新编译函数的所有客户端

inline关键字只是给编译器内联的建议,至于会不会真的内联,编译器会根据函数具体规模权衡时间空间效率之后选择是否内联

猜你喜欢

转载自blog.csdn.net/huifaguangdemao/article/details/109260485
今日推荐