C++:类和对象(上)

类的概念及定义

                类的概念:

        类(Class)是C++中面向对象编程的基础概念之一,它定义了一种数据类型,是一种用户自定义的数据结构。类可以看作是对象的蓝图或模板,描述了对象具有的属性(数据成员)和行成员函数)

                        

        如上图 外卖平台就是一个模板,而C语言更注重过程,考虑的是一个订单从出餐到送餐的过程,而C++除了注重过程还更加注重还关注整个外卖服务的各个方面。在C++中,你会把订单看作一个对象,这个对象不仅包含了订单的数据还包含了一系列与订单相关的行为。这些行为(或者说函数)与订单对象紧密相关,被封装在订单对象内部。

        C++则更偏向于以对象为中心,通过类和对象来组织代码,并且强调数据和行为的封装与抽象化

                类定义的格式:

        class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或者成员函数。

        

#pragma once
#include<iostream>
#include<stdlib.h>
class Stack
{
	void STInit(int capaticy = 4)
	{
		a = (int*)malloc(sizeof(int) * capaticy);
		_top = 0;
		_capaticy = capaticy;
	}

	void STPush(int x)
	{
		a[_top++] = x;
	}

	void Destroy()
	{
		free(a);
		a = nullptr;
	}

	int* a;
	int _top;
	int _capaticy;
};

        如上图这段代码是一个用C++编写的简单的栈(Stack)类的实现。可以看出和C语言中的栈的结构体类似但又有很大的区别。

        在类里不仅可以定义成员变量,更可以定义成员函数(这点在C语言上是不允许的)。

        可以看到通过使用类对栈进行初始化以及进行插入时的函数调用就会简洁很多,如果是C语言那么则还需要传地址会相对麻烦。

                类的访问限定符:

在C++中,访问限定符用于控制类(或结构体)的成员变量和成员函数对外部代码的可见性和访问权限。主要的访问限定符包括public(公共)、protected(保护)和private(私人)。

        public中文名为公共,顾名思义是所有人都可以用的。修饰的成员在类外可以直接被访问;protected和privated都具有隐私性,修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后往后才能体现出他们的区别。
        
class Stack
{
public:
	void STInit(int capaticy = 4);

	void STPush(int x);

	void Destroy();	

private:
	int* a;
	int _top;
	int _capaticy;
};

        上图小编将Stack类里的成员函数权限设定为public,将成员变量权限设置为私人。可以看出主函数中调用类里的成员函数是没有任何问题的,而一旦想要直接调用类里的成员变量则会发生编译错误,因为私人区域是不允许直接调用。

        上图的将成员变量和成员函数捆绑在一起,并加以保护,是为了防止外部直接访问和修改对象的内部状态。封装有助于隐藏对象的内部细节,同时提供了一个清晰定义的接口,使得程序员无需关心对象内部的实现细节,只需要通过公共接口与对象进行交互即可,这种就是类的第一特性:封装。

        封装的本质是⼀种更严格规范的管理,避免出现乱访问修改的导致类的属性被破坏的问题。

                类域:

        类同样拥有自己的域,类的所有成员都在类的作⽤域中,同时类域不影响变量⽣命周期。类域影响的是编译的查找规则,所以在类体外定义成员时需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。
        
        上图除了主文件,再次添加了两个文件一个头文件Fun.h与Fun.cpp。
        将类的声明放到头文件中,并将成员函数的定义放在Fun.cpp中,可以看到要在Fun.cpp中定义类中成员函数需要通过 : :(域作用限定符)编译器才能查找的声明在哪⾥,否则就会报错。

实体化

        实体化概念:

        ⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。
        类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只 是声明,没有分配空间,⽤类实例化出对象时,才会分配空间。
class Data
{
public:
	void Init(int year,int month,int data)
	{
		_year = year;
		_month = month;
		_data = data;
	}
	
	void Print()
	{
		cout <<  _year << "-" << _month << "-" << _data << endl;
	}

private:
	//变量只是声明并没有实际的开辟空间
	int _year;
	int _month;
	int _data;
};

int main()
{
	//实体化出对象d1与d2
	Data d1, d2;
	d1.Init(2022, 11, 11);
	d2.Init(2022, 12, 12);
	d1.Print();
	d2.Print();

}

        从上图可以看到,如果直接给Data类里的_data直接进行赋值会报错,而实体化出的对象d1则不会。这就类似于建房子,你不可能在图纸样板里面建房子,只能在实际的地面上才能。

        

                

        关于实体化里的对象大小:

                在了解实体化里对象大小的概念前需要了解结构体的内存对齐以及内存对齐的规则,如果有不清楚的可以看看小编之前写的一篇文章C语言结构体知识-CSDN博客

        

        从上图可以看出使用sizeof计算出Data类与对象d1的大小结果都是12,那上面又说成员变量只是声明没有分配空间。为什么sizeof还能计算出类的大小呢?其实要想明白也很简单,就好房子的图纸上都有标注空间长度大小,而d1又类似于实际去房子里丈量,两种方法都可以得知房子的尺寸。

        而通过sizeof发现,类的大小为12,刚好三个成员变量int的值。那么成员函数难道没有参与计算吗?

        此时将代码进行调试并转到反汇编指令时发现,d1.Init()与 d2.Init()都call向同一块空间,那么也就说明d1的成员函数与d2的成员函数是共用的,所以类成员函数的是存放在一个公共的代码区域段的地方,那么这样做也是为了节约空间。

        就好比对象1与对象2相约一起打篮球,而打篮球需要篮球场。篮球场可以建在对象1的家里同样也可以建在对象2的家里但这样做都会很浪费空间。那么将篮球场建立在一个公共的区域,既方便调用又节约了对象1与对象2自身的空间。

        

        通过上图运行代码,我们可以看到A1类既没成员函数也没成员变量,A2类只有一个成员函数。A1类的对象a与A2类的对象b通过sizeof计算出它们的大小都为1,这是为了确保每个对象在内存中占有独立的空间,即使是空类也需要有独特的地址。因为如果⼀个字节都不给,怎么表⽰对象存在过呢!

this指针:

        

        通过上图可以看到将Data类的d1与d2对象进行了初始化,并且输出他们的成员变量。但根据上面的知识我们可以得知,类成员函数是存在于公共代码段里的,而Print函数又没有参数但又却能准确的显示d1与d2对象中的参数,那编译器是怎么知道是调用d1还是d2呢?

        

        通过观察反汇编指令可以发现,编译器在调用Print函数之前会先将d1的地址与d2的地址压入ecx寄存器中然后再调用函数,但我们自己并没有去手动的将d1与d2的地址进行传参,那么这里就涉及到C++中的this指针。

        编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。⽐如Date类的Print的真实原型为void Print( Data* this),而类的成员函数中访问成员变量,本质都是通过this指针访问的也就是 cout << this-> _year << "-" << this->_month << "-" << this->_data << endl;

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

 

        

        

  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值