1.类和对象
1.1 C语言和C++处理问题的区别
在C语言中我们更关注解决问题的过程,分析出解决问题需要分为哪几步没通过调用函数来解决问题。而在C++中是把一个需要解决的问题或者设计的项目分为若干个不同的对象,依靠对象之间的交互解决问题。
1.2 类是什么,对象是什么
类是对对象进行描述的,是一个对象的模型,可以理解为类就像是一个房子的建造图纸,里面可以定义若干个的变量来描述房子的属性(比如:房子里有多少个房间,一个房间有多大,一个房间里装几个灯),但是和C语言结构体不一样的是,C++的类中是可以写函数的。
对象则是类的一个具体的表现形态,如果说类是一个房子的建造图纸的话,那么对象就是按照图纸盖出来的房子。
1.3 类和结构体的区别
类可以说是C语言结构体的一个升级版,那么咱们先来看看C语言中的结构体可以怎么定义。以下案例是C语言的一个结构体,其中struct ListNode是一个类型的名,我可以用它来定义struct ListNode类型的变量。
typedef struct ListNode
{
int val;
struct ListNode * next;
} LTN;
而在C++中,祖师爷本贾尼博士把struct升级成了类的概念。以下是C++定义类的案例,在编写完以下类了以后,我可以直接拿ListNode来定义一个对象了。
struct ListNode
{
int aval;
ListNode * next;
};
1.4 类的定义
定义类的关键字有两种:class、struct
(1)定义格式
class是定义类最常用的关键字,classname是类的名字,{}是类的主体,类的结束时一定要加分号,类体中的内容成为类的成员:类中的变量称为类的属性或者成员变量,类中的函数被称为类的方法或者类的函数。
class classname
{
// 包含成员函数和成员变量
}; //后面一定有分号
(2)两种定义的方式
1.声明和定义全部放在类体中,成员函数如果在类中定义,编译器可能将其当做内联函数处理。
class Person
{
public:
void showinfo()
{
cout<<_name<<" " <<_sex <<" "<<_age <<endl;
}
private:
char * _name;
char * _sex;
int _age;
}
2.声明和定义分离的类,类的声明放在.h文件中,成员函数定义让放在.cpp文件中,注意:成员函数名前需要加类名:: 这里写了一个栈作为参考案例,栈这个类的声明放在.h文件中,栈的定义放在.cpp文件中。
在.h文件中:声明函数和变量,并且在函数中设置缺省参数
#pragma once
struct Stack
{
void Init(int n = 4); //在声明中设置缺省参数
void Push(int x);
int * a;
int size;
int capacity;
};
在.cpp文件中:定义函数
#include<iostream>
#include"Stack.h"
void Stack::Init(int n)
{
a = (int *)malloc(sizeof(int)* n );
if(a == nullptr)
{
cout<<"malloc 申请失败";
return -1;
}
cpacity = n;
size = 0;
}
void Stack::Push(int x)
{
a[size++] = x;
}
2. 类的访问限定符及封装
2.1 访问限定符
C++实现封装的方式:用类将对象的属性和方法(类中的函数)结合在一块,通过访问权限选择性的将接口提供给外部的用户使用。访问限定符分为三种,如下图所示。
访问限定符说明
(1)public:谁都可以访问;
(2)protected 和 private:被protected和private修饰的成员,在类中可以随意访问,但是不能通 过外部直接访问。
(3)访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
(4)如果后面没有访问限定符,作用域就到 } 即类结束。
(5)class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
2.2 封装
面向对象的语言有三大特征:封装、继承、多态。 在类和对象阶段,主要是研究类的封装特性
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装本质上是一种管理,让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,JSB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑内部真正工作的事CPU、内存、显卡等硬件。
3. 类的实例化
用类创建一个对象的过程被称为类的实例化。类的本质上只是一种声明,它不占用任何的内存空间,但是类实例化的对象是占用内存空间的,如果说类是造房子的图纸的话,那么类实例化出来的对象就是一个实体的房子了。
#include<iostream>
class Date
{
public
void Init(int year , int month , int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1; //实例化对象d1
Date d2;
d1.Init(2024,4,14); //调用结构体内部的成员函数进行初始化
return 0;
}
在实例化的对象中,对象的大小就是类中所有成员变量加在一起的大小,是不包含成员函数的,为什么呢?因为成员变量是存在于对象中的,但是成员函数不存在与对象中,例如:一个小区里面有很多的房子,除此之外还有很多的公共设施像游泳池、小卖部等,小区里的公共设施就像是成员函数一样,是大家公用的,没有必要在每家每户都建一个游泳池,开一个小卖部。成员函数存放在代码段中也就是公共区域中结论:一个类的大小,实际就是该类中"成员变量”之和,当然要注意内存对齐注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
4.this指针
4.1 this指针的引出
我们调用对象中的成员函数的时候我们可以选择传递或者不传递实参,但是不管我们选择传不传参数,编译器都会传递一个默认的参数给到成员函数中,这个默认的参数是目标对象的地址。因此既然默认给成员函数传了一个地址,成员函数中其实也有一个隐藏的指针去接受这个地址。这个指针就是this指针。具体用法如下所示,在成员函数定义时,其中默认加了Date * const this 这个形参,在调用成员函数时,系统也会默认将d1的地址传过去,默认情况下不需要我们手动加。
#include<iostream>
using namespace std;
class Date
{
public:
void Init(Date * const this ,int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void print()
{
cout << this->_year << "/" << this->_month << "/" << this->_day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1; //实例化对象d1
d1.Init(&d1,2024, 4, 14); //调用结构体内部的成员函数进行初始化
d1.print(&d1);
return 0;
}
4.2 this的特性
(1)一般情况下,this指针存放在的栈中,在VS环境中存放在ECX寄存器中
(2)this指针只能在成员函数内部使用
(3)this指针本质上时“成员函数的形参”,当对象调用成员函数时,将对象地址作为实参传 递给this指针,所以对象中不存放this指针。
(4)this指针可以为空