食用指南:本文在有C基础的情况下食用更佳
这就不得不推荐此专栏了:C语言
♈️今日夜电波:ちるちる—REOL(对,我老婆唱的)
1:34 ━━━━━━️──────── 3:17
◀️ ⏸ ▶️ ☰
关注点赞收藏您的每一次鼓励都是对我莫大的支持
目录
一、类的引入
一个经典的案例
类的基本规则(重点)
二、类的定义
三、类的空间大小
四、在类内声明 类外定义 成员函数
五、【类的定义在头文件 成员函数 是在cpp文件中实现】(重要)
data.h
data.c
main.cpp
六、成员函数与全局函数的使用拓展-比较Cube类
typedef struct _Person {
char name[64];
int age;
}Person;//68B
typedef struct _Aninal {
char name[64];
int type; //动物种类
}Ainmal;//68B
void PersonEat(Person* person)
{
printf("%s 在吃人吃的饭!\n", person->name);
}
void AnimalEat(Ainmal* animal)
{
printf("%s 在吃动物吃的饭!\n", animal->name);
}
int main() {
Person person;
strcpy(person.name, "小明");
person.age = 30;
AnimalEat(&person);
return EXIT_SUCCESS;
}
这个案例代码运行的结果是什么呢? 他最后输出的是 “小明 在吃动物吃的饭!” 理所当然的,人不应该吃动物吃的饭啦QAQ,仔细观察问题出在了后面调用 AnimalEat() 这个函数时 居然把 Person这个结构体型的变量传入了这个函数!
你可能会很奇怪?为什么传错了不同类型的变量这个函数还能执行呢?这是因为:这两个结构体所占内存的空间大小都是相同的!因此,这个函数错误的识别了应该要传的参数!
注意:这个错误的传参在最新版本的vs中已经不能成功的运行了!
在这个案例中,我们应该可以体会到, 属性和行为应该放在一起, 一起表示一个具有属性和行为的对象。对此,C++针对这个错误,也就是为了防止错误的调用,避免问题发生,提出了封装的概念,也就是类。封装特性包含两个方面, 一个是属性和变量合成一个整体,一个是给属性和函数增加访问权限。
1. 把变量(属性) 和函数(操作) 合成一个整体, 封装在一个类中
2. 对变量和函数进行访问控制访问权限
3. 在类的内部(作用域范围内), 没有访问权限之分, 所有成员可以相互访问
4. 在类的外部(作用域范围外), 访问权限才有意义: public, private, protected
5. 在类的外部, 只有 public 修饰的成员才能被访问, 在没有涉及继承与派生
时, private 和 protected 是同等级的, 外部不允许访问
一图流~
class 类名
{
//公共的行为或属性
public:
// 受保护成员 //此通常少用因为很多都同private一样
protected:
//私有的行为或属性
private:
}
强调:private是私密的数据,只能被类内部访问,而public则是可以被外部、内部访问!一般来说:类的属性应该设置成私密的,也就在private下定义,而public下可以定义函数等来对这些属性进行修改、读取等等!
我们最常见到的应该是类似于这样的类:
class Cub
{
public:
int mL; // 长度
double mH; // 宽度
double mW; // 高度
}
经常刷题应该经常能看到(确信QAQ),通常完整的类是下面的这个例子
栗子:(此为一个求立方体体积以及面积的类)
class Cub {
public:
void setL(int l) { mL = l; }
void setW(int w) { mW = w; }
void setH(int h) { mH = h; }
int getL() { return mL; }
int getW() { return mW; }
int getH() { return mH; }
//立方体面积
int caculateS() { return (mL * mW + mL * mH + mW * mH) * 2; }
//立方体体积
int caculateV() { return mL * mW * mH; }
private:
int mL; //长
int mW; //宽
int mH; //高
};
根据以上我们所强调的,现在对属性设置成private,也就是mL、mW、mH。而public则是设置读、写功能的函数。
注意:这里并不是说属性一定要定义到private中,你当然可以在public中定义,此只是演示的效果。
在类外对public下的函数进行调用:
void text1()
{
Cub op1;
op1.setH(10);
op1.setL(20);
op1.setW(30);
cout << "op1 面积:" << op1.caculateS() << " 体积:" << op1.caculateV() << endl;
}
在类外对private下的属性进行调用: (报错!!!)
请看以下代码:
class Data
{
private:
//成员数据 占类的空间大小
int num;//4B
double data//8B
public:
//成员函数 不占类的空间大小
void setNum(int data)
{
num = data;
}
int getNum(void)
{
return num;
}
};
void test1()
{
printf("%d\n", sizeof(Data));//16B
}
实际上类所占的空间大小同结构体所占空间的大小的计算规则都是相同的,都是遵循内存对齐的原则的!
按照 成员数据 占类的空间大小 成员函数 不占类的空间大小 的原则
我们只计算 private中的成员数据 即:
事实真的是如此嘛?请看运行结果:
结论:我们可以按照计算结构体所占空间的方法去计算类的空间大小!
先看以下这个例子:
class Data
{
private:
int num;
double data;
public:
//成员函数 在类内 声明 类外定义
void setNum(int data);
int getNum(void);
};
void Data::setNum(int data)
{
num = data;
}
int Data::getNum()
{
return num;
}
由此可见:如果我们要在类外定义成员函数需要使用以下格式来定义:
函数返回类型 类名::函数名(对应定义所传参数)
{ 巴拉巴拉 }
当我们如下步骤创建类时:
我们可以按照以下例子的方式来创建:
#ifndef DATA_H
#define DATA_H
class Data
{
private:
int num;
public:
//设置num
void setNum(int n);
int getNum(void);
};
#endif // DATA_H
#include "data.h"
void Data::setNum(int n)
{
num = n;
}
int Data::getNum(void)
{
return num;
}
#include
#include"data.h"
using namespace std;
int main(int argc, char *argv[])
{
Data ob;
ob.setNum(200);
cout<<"num = "<
可以发现,这同我们日常创建另外的函数文件方式是差不多的,只需要多加使用便可熟悉了!
在观看此篇前我觉得你有必要先了解一下引用的知识:C++引用(这是链接快点!)
设计立方体类(Cube), 求出立方体的面积( 2ab + 2ac + 2bc )和体积( a * b * c), 分别
用全局函数和成员函数判断两个立方体是否相等。
class Cub {
public:
void setL(int l) { mL = l; }
void setW(int w) { mW = w; }
void setH(int h) { mH = h; }
int getL() { return mL; }
int getW() { return mW; }
int getH() { return mH; }
//立方体面积
int caculateS() { return (mL * mW + mL * mH + mW * mH) * 2; }
//立方体体积
int caculateV() { return mL * mW * mH; }
//成员方法
bool CubCompare(Cub& c) {
if (getL() == c.getL() && getW() == c.getW() && getH() == c.
getH()) {
return true;
}return false;
}
private:
int mL; //长
int mW; //宽
int mH; //高
};
//比较两个立方体是否相等
bool CubCompare(Cub& c1, Cub& c2) {
if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH()
== c2.getH()) {
return true;
}return false;
}
void test() {
Cub c1, c2;
c1.setL(10);
c1.setW(20); c1.setH(30);
c2.setL(20);
c2.setW(20);
c2.setH(30);
cout << "c1 面积:" << c1.caculateS() << " 体积:" << c1.caculateV()
<< endl;
cout << "c2 面积:" << c2.caculateS() << " 体积:" << c2.caculateV()
<< endl;
//比较两个立方体是否相等
if (CubCompare(c1, c2)) {
cout << "c1 和 c2 相等!" << endl;
}else{
cout << "c1 和 c2 不相等!" << endl;
} if(c1.CubCompare(c2)) {
cout << "c1 和 c2 相等!" << endl;
}else{
cout << "c1 和 c2 不相等!" << endl;
}
}
bool CubCompare(Cub& c1, Cub& c2) {
if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH()
== c2.getH()) {
return true;
}return false;
}
根据引用的定义,并且在全局函数比较两个Cube类时传两个参数是正常的,那为啥下面的成员函数仅仅需要传一个参就可以了呢?
bool CubCompare(Cub& c) {
if (getL() == c.getL() && getW() == c.getW() && getH() == c.
getH()) {
return true;
}return false;
}
这是因为成员函数是在类的内部所定义的,因此可以直接访问类内的数据,如果是比较本类以及另外一个类则无需再次去创建一个新的类,将另外一个类传参进入成员函数即可!
感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!
给个三连再走嘛~