欢迎来CILMY23的博客
本篇主题为 C语言转型之路:从C到C++的类与对象初探
个人主页:CILMY23-CSDN博客
个人专栏系列: Python | C语言 | 数据结构与算法 | C++
感谢观看,支持的可以给个一键三连,点赞关注+收藏。
写在前头:
面向过程和面向对象的认识:
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。面向对象都有以下三种特性:封装、继承、多态。
例如:人用洗衣机洗衣服,C语言关注的是如何洗衣服,而C++会将这件事拆分成多个对象,洗衣机,人,洗衣粉,衣服。我们关注这些对象,而不关心是如何洗衣服的。
目录
一、类和对象
1.1 类的引入
1.2 类的访问限定符
1.3 类的定义
1.3.1 声明和定义全在类中
1.3.2 声明和定义分离
1.4 类的封装
1.5 类的作用域
一、类和对象
在面向对象编程中,对象是类的一个实例。类是一个抽象的概念,它描述了一类对象共同的属性和行为。通过类可以创建多个具体的实例,这些实例就是对象。
对象可以是现实世界中的物体(如汽车、动物等)、概念(如账户、订单等)或者抽象数据类型(如栈、队列等)。每个对象都有自己的状态(属性)和行为(方法)。状态是描述对象的特征,而行为是对象能够执行的操作。
例如,如果有一个“汽车”类,那么具体的一辆汽车(比如一辆特斯拉Model 3)就是这个类的一个对象。这辆汽车有自己的颜色、速度、品牌等属性,同时它能够进行加速、减速、转向等行为操作。
1.1 类的引入
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现, 会发现struct中也可以定义函数。
例如:
typedef int DataType;
struct Stack
{
//栈的初始化
void Init(size_t capacity)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (nullptr == _array)
{
perror("malloc申请空间失败"); return;
}
_capacity = capacity;
_size = 0;
}
//插入
void Push(const DataType& data)
{
// 扩容
_array[_size] = data;
++_size;
}
DataType Top()
{
return _array[_size - 1];
}
//栈的销毁
void Destroy()
{
if (_array)
{
free(_array);
_array = nullptr; _capacity = 0;
_size = 0;
}
}
DataType* _array;
size_t _capacity;
size_t _size;
};
我们发现C++兼容C,在c++中同样可以运行C的玩法,同时我们把其中的变量叫做成员变量,其中的函数称为成员函数。但C++更喜欢用class来定义上述的结构体,于是类的结构就确定了。
类的结构如下:
//类的定义
class classname
{
//类体,由类的成员变量和成员函数构成
//…………………………
}; //注意有分号
class 是C++中类的关键字,classname为类的名字,{}为类的主体,注意和结构体一样,末尾的分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者 成员函数。
我们习惯的在成员变量前加一个横杠以用来区分形参和成员变量。
1.2 类的访问限定符
C++中类的访问限定符有三种,
- public 公有
- protected 保护
- private 私有
在目前这个学习阶段我们可以认为2,3没有区别(实际有区别),我们主要讲还是1,3。
访问限定符的特点:
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } ,即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
在这里我们使用日期类举例 :
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.Init(2024, 04, 17);
//d1.year++; 无法被访问
return 0;
}
我们想让类的成员被访问就用公有,不想被访问就私有,如果我们这里把class改成struct也是可以的。
1.3 类的定义
1.3.1 声明和定义全在类中
注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
我们以学生类为例:
class Student
{
public:
void StuInit(const char* name,int age,const char* sex)
{
strcpy(_name, name);
_age = age;
strcpy(_sex, sex);
}
void showInfo()
{
cout <<"名字:" << _name << " "
<<"年龄:" <<_age << " "
<<"性别:" <<_sex << endl;
}
private:
char _name[20];
char _sex[20];
int _age;
};
int main()
{
Student s1;
s1.StuInit("zhangsan", 18, "male");
s1.showInfo();
return 0;
}
1.3.2 声明和定义分离
假设我们要声明和定义分离,这里我们用栈来举例:
Stack.h:
//头文件我们放成员函数,成员变量的声明
class Stack
{
public:
//成员函数
void Init(int n);
void Push(int x);
private:
//成员变量
int* a;
int top;
int capacity;
};
Stack.cpp:
#include"Stack.h"
void Init(int n = 4)
{
a = (int*)malloc(sizeof(int) * n);
if (a == NULL)
{
perror("malloc fail");
return;
}
capacity = n;
top = 0;
}
void Push(int x)
{
//...
a[top++] = x;
}
但是我们发现在上述情况下,编译器会报错,这是因为类也有自己的作用域,编译器会从全局域,局部域搜索,找不到就会报错了。所以我们需要去类中搜索。
Stack.cpp
#include"Stack.h"
void Stack::Init(int n = 4)
{
a = (int*)malloc(sizeof(int) * n);
if (a == NULL)
{
perror("malloc fail");
return;
}
capacity = n;
top = 0;
}
void Stack::Push(int x)
{
//...
a[top++] = x;
}
类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::,一般情况下,更期望采用第二种声明和定义分离的方式。
1.4 类的封装
面向对象的三大特性:封装、继承、多态。(是面向对象编程都有的)
C++中,在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来 和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用 户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日 常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如 何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计 算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以 及键盘插孔等,让用户可以与计算机进行交互即可。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来 隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
C++将数据和方法都放到类中,利用访问限定符对成员进行限制,想访问的设置成公有,不想访问的设置成私有。
1.5 类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
如果我们需要访问类域,就需要用::来访问
例如:当我们在声明和定义分离的时候,我们就会将类前面加个作用域操作符,来表明是哪个类域的。
class Student
{
public:
void StuInit(const char* name, int age, const char* sex);
void showInfo();
private:
char _name[20];
char _sex[20];
int _age;
};
void Student::StuInit(const char* name, int age, const char* sex)
{
strcpy(_name, name);
_age = age;
strcpy(_sex, sex);
}
void Student::showInfo()
{
cout << "名字:" << _name << " "
<< "年龄:" << _age << " "
<< "性别:" << _sex << endl;
}
int main()
{
Student s1;
s1.StuInit("zhangsan", 18, "male");
s1.showInfo();
return 0;
}
一些总结:
- C++ 兼容C struct的用法,但是同时升级成了类,可以将函数写于类中
- 类要定义哪些东西是不确定的,类要设计哪些东西,取决于要完成哪些东西
- 类提供了三种访问限定符,它们分别是public(公有),private(私有),protected(保护)
- class 的访问默认是private,而struct默认访问是public
- 声明和定义分离的时候,成员函数的定义需要加 类名::
- 封装的本质是一种管控
感谢各位同伴的支持,本期C++篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。