文章目录:
1. 面向过程和面向对象
- C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题
- C++是基于面向对象的,关注的是对象 ,将一件事情拆分成不同的对象,靠对象之间的交互完成
- 面向对象语言的四大特性:抽象,封装,继承,多态
2. 类
2.1 前言
在C语言中,结构体中只能定义变量,如下图所示:
#include<stdio.h>
#include<stdlib.h>
typedef struct SqList
{
int* base;
int capacity;
int size;
}SqList;
void InitSqList(SqList* plist)
{
plist->base = (int*)malloc(sizeof(int)* 10);
plist->capacity = 10;
plist->size = 0;
}
}int main()
{
SqList t;
InitSqList(&t);
return 0;
}
此时,我们会发现初始化函数InitSqList和结构体并没有多大的关系,但当我们将函数InitSqList放入结构体中我们会发现,C语言并不能编译通过
在C++中,结构体内不仅可以定义变量,也可以定义函数
如上结构体的定义C++中更喜欢用class来代替
代码测试如下:
#include<iostream>
using namespace std;
class SqList
{
public:
int* base;
int capacity;
int size;
void InitSqList(SqList* plist)
{
plist->base = (int*)malloc(sizeof(int)* 10);
plist->capacity = 10;
plist->size = 0;
}
};
int main()
{
SqList t;
t.InitSqList(&t);
return 0;
}
此时我们会发现在C语言中使用结构体和在C++中使用class效果类似,只是C语言在结构体中不能定义函数
2.2 类的定义
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数
2.3 类的两种定义方式
- 声明和定义全部放在类体中
注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理
举例如下:
#include<iostream>
using namespace std;
class goods
{
public:
int price;
int count;
void show()
{
cout << "This is show" << endl;
}
};
int main()
{
goods t;
t.show();
return 0;
}
- 声明放在类体中,定义放在类体外
注意:需要在定义的函数名前加上类名和作用域解析符( :: )
#include<iostream>
using namespace std;
class goods
{
public:
int price;
int count;
void show();
};
void goods::show()
{
cout << "This is show" << endl;
}
int main()
{
goods t;
t.show();
return 0;
}
3. 类的封装及访问限定符
3.1 封装
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
上面这句话我们可以这样理解,封装的本质是一种管理,而封装的管理方法就像我们管理兵马俑一样,当我们发现兵马俑后什么都不管,兵马俑就会被随意破坏,所以我们需要建一座房子把兵马俑封装起来,但我们的目的不是为了全封装起来不让别人看。所以,我们开放了售票通道,可以买票突破封装在合理的监管机制下进去参观。类也是一样,我们如果我们使用的成员变量和类方法不想让别人看到就使用访问限定符protectcted/private把成员封装起来,开放一些共有的成员函数对成员合理的访问
3.2 访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
那么访问限定符有哪些呢?(如下图所示)
protected和private封装的成员我们不能进行直接操作,而public修饰的成员我们可以在类外直接访问
限定符的说明:
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- class的默认访问权限为private,struct为public(因为struct要兼容C)
注意: 访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
使用如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class goods
{
public:
void RegisterGoods(char* _name,float _price,int _count)
{
strcpy(name , _name);
price = _price;
count = _count;
}
char* GetName()
{
return name;
}
float Getpirce()
{
return price;
}
int Getcount()
{
return count;
}
float GetTotalPrice()
{
return price * count;
}
private:
char name[10];
float price;
int count;
};
int main()
{
goods t1,t2;
t1.RegisterGoods("数据结构",22,30);
t2.RegisterGoods("C++教程", 17.8, 80);
cout << t1.Getcount() << endl;
cout << t2.Getpirce() << endl;
return 0;
}
3.3 面试题:C++中struct和class的区别是什么?
C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。和class是定义类是一样的,区别是struct的成员默认访问方式是public(公有),class是struct的成员默认访问方式是private(私有)。
4. 类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。
举例如下:
#include<iostream>
using namespace std;
class goods
{
public:
int price;
int count;
void show();
};
//此处需要指定show是属于goods这个类域的
void goods::show()
{
cout << "This is show" << endl;
}
int main()
{
goods t;
t.show();
return 0;
}
5. 类的实例化(本质开辟空间)
类创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- . 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
如下图所示即是一个实例化过程:
6. 类对象的大小计算
一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。
类对象的大小计算类似于C语言中结构体的大小计算,具体计算规则参考 [结构体大小计算]
类大小计算与结构体大小计算不同点:
- 空类的大小是一个字节
- 成员函数不占字节数
- 只有成员变量才占大小
7.类对象的存储方式
- 对象中包含类的各个成员
缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。
- 只保存成员变量,成员函数存放在公共的代码段