澄迈住房和城乡建设局网站,手机版网页制作,游戏私人服务器搭建,成都广告制作厂家前言#xff1a;本文主要介绍有关C入门需掌握的基础知识#xff0c;包括但不限于以下几个方面#xff0c;这里是文章导图#xff1a;
本文较长#xff0c;内容较多#xff0c;大家可以根据需求跳转到自己感兴趣的部分#xff0c;希望能对读者有一些帮助 那么本文也主要…前言本文主要介绍有关C入门需掌握的基础知识包括但不限于以下几个方面这里是文章导图
本文较长内容较多大家可以根据需求跳转到自己感兴趣的部分希望能对读者有一些帮助 那么本文也主要以导图为思路进行分享话不多说让我们开始吧。
一、关于类的理解与意义
1、理解
什么是类呢可以直接根据其表面来理解。这个“类”我们常说的给事物分类的“类”比如动物类交通工具类等等。通过给不同的事物进行分类能让我们更有条理性、更系统地认知这个世界。同样的道理类的设计可以让我们的代码编写更具逻辑性、可维护性等等。以上就是对类的简单理解。
2、意义
那么类的设计有什么意义呢基本的意义上述也提到了能增强代码的可维护性等它能将具有协同功能代码封装成一个整体从而更好地进行管理更多对其意义的感知还是需要通过不断的学习和代码实践来逐步加强。
关于类和对象的更形象理解方式大家感兴趣地可以去搜搜文章和书籍本文主要还是以学习笔记的方式来展现知识内容这里就不再赘述。
二、类的定义方式
1、关于兼容C后的结构体
由于C兼容C所以在C中结构体被升级成了类。在C中的结构体只能定义成员变量升级成类后也可以定义成员函数。但二者仍有一些区别下文会继续进行说明。
2、定义方式
类的定义方式如下
class typename
{};其中class为定义类的关键字typename为用于定义该类的类名花括号中为类的具体内容最后别忘了分号。
在实际工程中定义类时我们可以根据需求将类声明主要是其中成员函数的声明放在头文件中在.cpp文件中再对类中的成员函数进行定义。
三、类的访问限定符及封装的理解
类访问限定符是C实现封装的主要方式。通过访问限定符可以选择性地将类中的成员展现给外界用户。和平常被我们使用的电子产品一样都是将简单易用的功能展现给我们而将复杂的实现细节封装起来。
1.类的访问限定符
1类的访问限定符一共有三种分别是public、protected、private 对以上三种访问限定符的说明如下
被pubilc修饰的成员能在类外直接访问被protected和private修饰的成员不能在类外直接访问PS关于protected和private的区别在继承章节会提到平常使用可认为二者类似访问限定符的作用范围是从当前访问限定符开始到下一个访问限定符出现若下一个访问限定符一直未出现则右花括号为止。class关键字定义的类默认的访问权限为privatestruct关键字定义的类的默认范围权限为public兼容C
2类访问限定符在程序生命周期中作用的阶段编译阶段。即访问限定符只在编译阶段有用当数据映射到内存后没有任何访问限定符上的区别。
2、对封装的理解
封装是面向对象的三大特性之一封装、继承、多态。对封装的理解其实很简单前文也有谈到其实就是将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节对外仅公开使用工具接口来和对象进行交互。本质上属于一种管理让用户更方便的使用类也让类的设计更加规范化。
四、类的作用域与实例化
1、类的作用域
类的作用域也属于“域”的一种至此我们所认识的“域”一共就有如下三种
局部作用域全局作用域命名空间域类作用域
在笔者的另一篇文章【逐步剖C】-第一章-C入门知识的命名空间部分中提到了用域访问符::访问命名空间这里我们也有该符号的使用需求请看 在类外定义成员函数时需使用域访问符指明成员函数属于哪个类域请看下面代码例
class test
{
public:void testFunc();
}void test::testFunc()
{//...
}2、类的实例化
类的实例化本质就是通过类创建一个对象实例化出来的对象占实际的物理空间存储类的成员变量。由此可见类在没有实例化之前系统并没有为其成员变量并开实际的空间在这个阶段成员变量仅是声明当进行类的实例化时成员变量才得到整体定义。
这里有一个形象的理解方式 类的实例化过程就像拿着建筑设计图造出房子的过程。类就好比设计图仅对房子中的内容、布局等进行规划与设计并没有实体的建筑存在。所以仅有一个类的定义本质是不占空间的只有实例化出对象后才占物理空间而实际存储数据同理也不能直接在类外对类中声明的成员变量进行赋值就好比设计图中不能直接住人。
五、类对象的大小计算
这里通过三个类的例子进行对类对象的大小计算的说明
// 类中既有成员变量又有成员函数
class A1 {
public:
void f1(){}
private:
int _a;
};// 类中仅有成员函数
class A2 {
public:
void f2() {}
};// 类中什么都没有---空类
class A3
{};上面三个类实例化出的对象的大小分别为4字节、1字节、1字节。 解释 在类中对于成员变量和成员函数的大小计算不同
对于成员变量相同类实例化出的每个对象的成员变量是不一样的就好比同一张设计图造出来的房子都有卧室但这两个卧室一定是不同的计算它们的大小时和结构体一样采用内存对齐的方法进行计算即可。关于内存对齐可以看看笔者这篇文章【逐步剖C】-第十章-自定义类型之结构体、枚举、联合对于成员函数相同类实例化出的每个对象其实是一样的成员函数就像是篮球场、健身房等场所不用每家都建而建成公共的这样就避免了由于重复而引起的空间浪费那么类中的成员函数存储方式类似其会以成员函数表的形式放在一个公共的代码段中当类的对象需要调用成员函数时就到这个公共代码段中找对应的函数地址来完成调用其实际不在类中不占空间。
验证
class A
{
public:void Test(){cout void Test() endl;cout _a endl;}
private:int _a 0; //成员变量缺省值后续章节会说明
};
int main()
{A a1;A a2;a1.Test();a2.Test();
}运行后转到反汇编 可以看到同一个类的两个不同对象所调用的成员函数的地址相同PS图中红框就是代码中的Test函数蓝框是A类的默认构造函数后续章节会进行说明。
那么在最开始的代码例中类A1的大小即为其成员变量的大小类A2和类A3的大小类似编译器会给他们一个字节来唯一标识这个类的对象。
六、this指针
1、this指针的本质
场景引入在上面的例子中我们通过类A实例化了两个对象并且这两个对象都调用了成员函数Test()那么编译器是如何知道是哪个对象调用的呢这就是this指针解决的问题了。
C编译器给每个非静态的成员函数增加了一个隐藏的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)指针中的内容即为对象本身的地址在函数体中所有成员变量的操作都是通过该指针去访问。只不过所有的操作对用户是透明的即用户不需要来传递编译器自动完成。 即例子中两条调用语句其实可理解为
a1.Test(a1);
a2.Test(a2);需要注意的是如上仅作为一种理解方式实际不能这么写因为编译器规定this指针不能在实参和形参显示传递仅可以在成员函数内部显示使用。 如
class A
{
public:void Test(){cout void Test() endl;cout _a endl; //编译器自动处理this指针//也可显示使用写为cout this-_a endl;}
private:int _a 0; //成员变量缺省值后续章节会说明
};2、this指针的特性
this指针的类型其实为const 类的类型*如上A类的对象的this指针类型就为A* const即不能改变指针所指向的对象而可以改变对象中的具体内容成员变量等只能在成员函数中显示调用this指针本质上是成员函数的形参当对象调用成员函数时编译器一般通过ecx寄存器自动将对象地址作为实参传递给该形参。故在类的对象中不存储this指针
3、关于this指针的一些问题
了解了this指针的特性后下面有一些常被提起的关于this指针的问题请看
this指针可以为空吗 可以通过下面这一段代码来认识并解决这个问题
class A
{public:void Print(){cout Print() endl;}void PrintA(){cout _a endl;}
private:int _a;
};int main()
{A* p nullptr;p-Print();p-PrintA();return 0;
}p是一个A类对象的指针将其赋值为空指针后用以模仿this指针来调用A类中的成员函数。运行结果如下 可以看到第一个函数Print()正常调用在调用第二个函数时系统崩溃。原因很明显p是一个空指针在调用第一个成员函数时本质上并没有访问该指针所指向位置的内存对象的具体内容而在调用第二个成员函数时程序想访问并输出类的成员变量_a那么此时的行为就相当于解引用一个空指针而去访问其指向的内容也就是我们常说的野指针问题故造成了程序的崩溃。 综上this指针一般情况下不会为空。
this指针存储在哪里 第二个问题其实在介绍this指针的特性时已给出了答案this指针本质上是成员函数的形参那么既然是形参也就是局部变量那就一定存储在栈区当中。
本章完。
看完觉得有觉得帮助的话不妨点赞收藏鼓励一下有疑问或有误地方的地方还请过路的朋友们留个评论多多指点谢谢朋友们