类和对象(上)

目录

一、类的定义

1.1类定义的格式

1.2访问限定符

二、实例化

2.1实例化的概念

2.2对象大小的计算

三、this指针

3.1this指针的使用

3.2有关this指针的样例

​编辑

四、C++和C语言实现Stack的对比


一、类的定义

1.1类定义的格式

C++中类的定义和C语言中结构体类型的定义非常相似,我们先来看C语言中结构体类型的定义,进而延申到C++中类的定义。

C语言中结构体类型的定义:

cpp 复制代码
struct book
{
	char book_name[100];
	char book_suthor[20];
	float book_price;
	char id[20];
};

C++中类的定义,需要用到class关键字,然后后面加类名,紧接着{}中为类的主题,{}后面紧跟着分号,类的定义如下(以日期类为例):

cpp 复制代码
class Data
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << _year << '/' << _month << '/' << _day << '/' << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

我们对比C语言中结构体类型的定义和C++中类的定义,可以发现两者存在如下区别:

1.结构体类型中只有成员变量(成员属性),而类类型中除了成员变量(成员属性)外,还多了一种成员------成员函数,如上述日期类中的Init函数。

2.类类型中还存在访问限定符(如上述日期类中的public、private)来限定类类型中成员的访问权限。

在C++中struct也可以用来定义类,如下代码所示:

cpp 复制代码
struct book
{
public:
	void Init()
	{

	}
private:
	char book_name[100];
	char book_suthor[20];
	float book_price;
	char id[20];
};

C++中struct定义的类和class定义的类,两者的区别在于:struct定义的类成员的默认访问权限为共有访问(public),class定义的类成员的默认访问权限为私有访问(private)。

1.2访问限定符

在上述类的定义中,我们已经提到了public和private两种访问限定符,访问限定符有以下三类,分别为共有、私有和保护:

访问限定符的作用是限制类外成员对类中成员的访问权限。

二、实例化

2.1实例化的概念

我们用类类型创建对象的过程,称为实例化。如下代码:

cpp 复制代码
#include<iostream>
using namespace std;
class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << '/' << _month << '/' << _day << '/' << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data d1;
	Data d2;
	Data d3;
	d1.Init(2024, 1, 20);
	d2.Init(2024, 1, 21);
	d3.Init(2024, 1, 22);
	return 0;
}

main函数中的d1、d2、d3便是Data类所创建(实例化)的对象。

2.2对象大小的计算

在计算对象大小之前,我们需要知道:在C++中通过类可以创建多个对象,而每个对象各自有相互独立的成员变量,但是成员函数用的是同一个,而成员函数放在一个公共区域内供多个对象进行调用,所以我们在计算对象的大小时,只需计算对象中成员变量的大小。

对象大小的计算和结构体大小的计算方法是一致的,都要用到内存对齐规则。内存对齐规则如下:

除此之外,在对象的计算中,有一种特殊的类需要我们注意,该类称为空类,空类的特点是没有成员变量,如下代码所示:

cpp 复制代码
class A
{
public:
	void Print()
	{
		//...
	}
};
class B
{};

空类没有成员变量可以计算大小,但是空类统一占据1个字节,原因在于空类也要用来定义对象,若空类大小是0个字节,就无法定义对象开辟空间,所以这里1个字节的作用纯粹是为了占位标识对象存在。

三、this指针

3.1this指针的使用

在上述的Data类中有两个成员函数Init和Print,成员函数体内没有关于不同对象的区分,但是d1、d2在调用成员函数时,成员函数是如何准确的访问到d1和d2呢?this指针便用来解决这里的问题。

this指针默认的存在于每一个成员函数形参部分的第一个位置。比如Data类中的Init的真实原型为

cpp 复制代码
void Init(Data* const this,int year,int month,int day);

成员函数中访问成员变量,本质都是通过this指针进行访问的,如下代码所示:

cpp 复制代码
class Data
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << this->_year << '/' <<this-> _month << '/' <<this-> _day << '/' << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

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

3.2有关this指针的样例

样例1:

样例2:

样例3:

四、C++和C语言实现Stack的对比

面向对象有三大特性:封装、继承、多态。而C++中的类便体现出封装这一特性,这一特性可以通过C和C++中实现Stack的差异中体现出来:

C语言实现:

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedefintSTDataType;
typedefstructStack
{
STDataType*a;
inttop;
intcapacity;
}ST;
voidSTInit(ST*ps)
{
assert(ps);
ps->a=NULL;
ps->top=0;
ps->capacity=0;
}
voidSTDestroy(ST*ps)
{
assert(ps);
free(ps->a);
ps->a=NULL;
ps->top=ps->capacity=0;
}
voidSTPush(ST*ps,STDataTypex)
{
assert(ps);
//满了,扩容
if(ps->top==ps->capacity)
{
intnewcapacity=ps->capacity==0?4:ps->capacity*2;
STDataType*tmp=(STDataType*)realloc(ps->a,newcapacity*
sizeof(STDataType));
if(tmp==NULL)
{
perror("reallocfail");
return;
}
ps->a=tmp;
ps->capacity=newcapacity;
}
ps->a[ps->top]=x;
ps->top++;
}
boolSTEmpty(ST*ps)
{
assert(ps);
returnps->top==0;
}
voidSTPop(ST*ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
STDataTypeSTTop(ST*ps)
{
assert(ps);
assert(!STEmpty(ps));
returnps->a[ps->top-1];
}
intSTSize(ST*ps)
{
assert(ps);
returnps->top;
}
intmain()
{
STs;
STInit(&s);
STPush(&s,1);
STPush(&s,2);
STPush(&s,3);
STPush(&s,4);
while(!STEmpty(&s))
{
printf("%d\n",STTop(&s));
STPop(&s);
}
STDestroy(&s);
return0;
}

C++实现:

cpp 复制代码
#include<iostream>
usingnamespacestd;
typedefintSTDataType;
classStack
{
public:
//成员函数
voidInit(intn=4)
{
_a=(STDataType*)malloc(sizeof(STDataType)*n);
if(nullptr==_a)
{
perror("malloc申请空间失败");
return;
}
_capacity=n;
_top=0;
}
voidPush(STDataTypex)
{
if(_top==_capacity)
{
intnewcapacity=_capacity*2;
STDataType*tmp=(STDataType*)realloc(_a,newcapacity*
sizeof(STDataType));
if(tmp==NULL)
{
perror("reallocfail");
return;
}
_a=tmp;
_capacity=newcapacity;
}
_a[_top++]=x;
}
voidPop()
{
assert(_top>0);
--_top;
}
boolEmpty()
{
return_top==0;
}
intTop()
{
assert(_top>0);
return_a[_top-1];
}
voidDestroy()
{
free(_a);
_a=nullptr;
_top=_capacity=0;
}
private:
//成员变量
STDataType*_a;
size_t_capacity;
size_t_top;
};
intmain()
{
Stacks;
s.Init();
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
while(!s.Empty())
{
printf("%d\n",s.Top());
s.Pop();
}
s.Destroy();
return0;
}
相关推荐
zhuqiyua7 小时前
第一次课程家庭作业
c++
只是懒得想了7 小时前
C++实现密码破解工具:从MD5暴力破解到现代哈希安全实践
c++·算法·安全·哈希算法
m0_736919107 小时前
模板编译期图算法
开发语言·c++·算法
玖釉-7 小时前
深入浅出:渲染管线中的抗锯齿技术全景解析
c++·windows·图形渲染
【心态好不摆烂】7 小时前
C++入门基础:从 “这是啥?” 到 “好像有点懂了”
开发语言·c++
dyyx1117 小时前
基于C++的操作系统开发
开发语言·c++·算法
AutumnorLiuu7 小时前
C++并发编程学习(一)——线程基础
开发语言·c++·学习
m0_736919107 小时前
C++安全编程指南
开发语言·c++·算法
阿猿收手吧!8 小时前
C++ std::lock与std::scoped_lock深度解析:从死锁解决到安全实践
开发语言·c++
2301_790300968 小时前
C++符号混淆技术
开发语言·c++·算法