往期文章: C++学习笔记
文章目录
前言
C++的类与对象概念是从C语言继承发展而来的。类继承自结构,“对象”的概念是C++的创新之处。
通过对类的使用我们可以极大的简化代码的编写流程,提高人编程的思维连贯性。如:在C++的编写规则下实现队列排列的方法被合并为了一个类,这个类既包含实现队列所需的变量又包含函数,这使得我们可以在编写队列时可以直接调用与相关的各种其函数。
比喻和理解
C语言实现一个功能
C语言实现功能就像是:装修工人C要装修自己的房子,C在厨房装修水池时去工作车上拿扳手,水池修好后把扳手放回车上,走回厨房后发现要装油烟机,又要用扳手,又去车上拿扳手,拿了扳手回来一看发现拿错了拿的是锤子,只能再拿,等厨房所有东西装好后又把扳手放回车上,第二天C装修卧室,他去车上拿锯子,发现锯子被别人当钢板拿去用了,问了很多人才知道是同事借的,同事用锯子当钢板还出了事故;C用完锯子后又放回车上,如此重复,直到整个房子装修完毕。效率低下,令人咋舌。
C语言实现功能时,函数与变量分开,当我们想要实现功能时需要分别设立,即一个结构装变量,一堆函数装变化,这些变量和变化要组合在一起使用,各个函数间需要依靠传参来有序工作,这个过程及其冗杂且出错率很高,如:顺序排错了、参数传错了、函数名用错了。
C++实现一个功能
C++实现功能就像是:装修工人C++装修自己的酒店,C++准备了几个工具袋,工具袋上分别写着厨房、卧室等房间名,并全写了“只准借给XXX”,C++提前准备工具放在工具袋上,然后把这些工具袋丢到对应的房间里去,工作时工具袋挂身上,需要什么工具就直接拿,用完了放回去,去什么房间就在身上挂什么工具袋。
C++实现功能时所需要的函数和变量可以放在一个类里面,实现功能需要什么变量和函数就直接在类里面定义变量,变量和函数的顺序可以随意排,还可以用访问限定符限定使用它们的途径,防止误用。
C语言的旧问题:
- 实现一个功能时所需的变量和函数要分开存放;
- 实现一个功能时要反复地从不同的结构里调用变量和各种函数;
- 编写完成后去调试很可能忘了参数类型以及参数范围,又要回去看结构和函数定义;
- 实现多个功能后再去实现一个新的功能时会发现之前函数定义又多又杂,很难分清各个函数属于什么功能;
- 使用变量时容易误用全局变量,运行结果错误后必须调试才能发现问题,勘误成本大。
一、面向过程与面向对象
C语言面向过程指编码者的工作是:对实现一个功能所需要的过程进行编码,主要考虑过程;
C++基于面向对象指编码者的工作是:实现一个功能就面向对象进行编码并考虑部分过程进行编码,主要考虑对象。
在实践中可以发现,当我们面向对象进行编码的时同步完成了面向过程的思考,这使我们的思考高效简洁。
二、类
1.类的特点
C++的类继承了C语言结构体定义变量的能力,且开创性的获得了定义函数的能力。即,C++的类可以同时定义变量与结构体,编写可变量带方法一口气实现一个功能。
代码如下:
#include<stdio.h>
#include<iostream>
using namespace std;
typedef int DataType; //定义一个变量类型
//定义一个类,包含变量与函数,我们以一个队列为例
struct try_stack
{
void Init(size_t capacity)
{
//开辟内存空间
_arr = (DataType*)malloc(sizeof(DataType) * capacity);
if (nullptr == _arr)
{
perror("malloc申请空间失败");
return;
}
_capacity = capacity; //将开辟的内存空间大小数字赋给变量
_size = 0; //定义这个队列的大小
}
//队列尾插
void Push(const DataType& data)
{
_arr[_size] = data;
++_size;
}
//在C语言里我们需要自己注意队列的尾部元素的角标,
DataType Top() //而在C++里我们可以自定义一个函数固定代表尾部元素
{
return _arr[_size - 1];
}
//释放队列所占的内存空间
void Destory()
{
if (_arr)
{
free(_arr); //释放数组空间
_arr = nullptr; //释放指针空间
_capacity = 0;
_size = 0;
}
}
//定义一个队列的各个变量,预备接受赋值
DataType* _arr;
size_t _capacity;
size_t _size;
};
int main()
{
try_stack s;
s.Init(4); //初始化队列
s.Push(5); //为队列尾插元素
s.Push(6);
cout << s.Top() << endl; //打印尾部元素
s.Destory(); //释放开辟的空间
return 0;
}
2.定义一个类——关键字class
class className //类名
{
//类体:由成员函数与成员变量组成
};//类的后面记得加分号
ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略(这是将类与函数区别的标志)。
类体里面的所有内容称为类的成员:
- 变量称为类的属性或成员变量;
- 函数称为类的方法或者成员函数。
类的两种定义方式:
- 方法一:声明和定义全部放在类体中(PS:成员函数如果在类中定义,编译器会根据自身设定将其作为内联函数处理。)
- 方法二:类的声明放在 .h 文件中,成员函数定义放在 .cpp 文件中,注意:成员函数名前需要加类名 :: (建议采用方法二,有利于检查传参错误和功能构思)
代码如下(示例):
#include<stdio.h>
#include<iostream>
using namespace std;
struct call //函数call的类体有成员变量和成员函数,用以演示方法一的情形
{
int num = 123456;
void prt(int a)
{
printf("%d\n", a);
printf("%d\n", num);
}
};
int main()
{
call s; //类实体化
cout<< s.num << endl; //打印成员变量
s.prt(666); //调用成员函数
return 0;
}
3.类的访问限定符与封装
a)访问限定符说明——规定类的成员可以被谁访问
- public修饰的成员在类外可以直接被访问(public访问限定符可以彻底开放成员的使用权限)
- protected和private修饰的成员在类外不能直接被访问
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止(访问权限的分隔标准)
- 如果一个访问限定符后面没有其他访问限定符,则作用域就到最近的 }为止, 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C语言,C语言没有访问限定符)
PS:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别(访问限定符只是我们编译时给程序员的思考辅助符号)
b)封装
面向对象的三大特性之一——封装
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。(就是给你一个黑盒子,往里面输入合法的数据,它给你输出正确的结果)
封装本质上是一种管理,让用户更方便使用类。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
c)类的实例化
定义一个类就是自定义一个模板,里面装着变量和方法,我们可以按着这个模板大规模定义各种变量,然后对这些变量使用同一种方法输出结果。
3.类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。