珠海网站建设珠海,天津雍鑫建设投资集团网站,wordpress右侧的工具栏,昆山网页设计公司文章目录 一、前言二、类1. 基本概念2. 类的封装3. 使用习惯成员函数定义习惯成员变量命名习惯 三、对象1. 基本概念2. 类对象的存储规则 四、this 指针1. 基本概念2. 注意事项3. 经典习题4. 常见面试题 一、前言
在 C 语言中#xff0c;我们用结构体来描述一个事物的多种属性… 文章目录 一、前言二、类1. 基本概念2. 类的封装3. 使用习惯成员函数定义习惯成员变量命名习惯 三、对象1. 基本概念2. 类对象的存储规则 四、this 指针1. 基本概念2. 注意事项3. 经典习题4. 常见面试题 一、前言
在 C 语言中我们用结构体来描述一个事物的多种属性。
struct person
{int age;char name[10];
};而 C 则引入了类相比结构体内只能定义变量类还可以定义函数。 下面声明一个类类名为person
//class关键字
class person
{void init(...){...}int age;char name[10];
};上面代码只是类的声明没有占用实际的空间。 用类创建对象称作类的实例化。 实例化的对象才会占用实际的物理空间。
创建对象类名 对象名 例子
person a;上述代码创建了一个person类的对象a对象才占有实际空间。
而 C 语言中的struct关键字在 C 中也升级成了类不过 C 中的struct关键字依然兼容 C语言的结构体写法。
//C 中的类
struct person
{void init(...){...}int age;char name[10];
};
//创建一个person类的对象b
person b;//C 语言中的结构体
struct person
{int age;char name[10];
};
//创建一个结构体变量c
struct person c;
//也可以这样写此时person被看作一个类
person c;二、类
1. 基本概念
类中的内容称为成员。 类中的变量称为属性或成员变量类中的函数称为方法或成员函数。
2. 类的封装
C 中的类是用于实现封装的封装是面向对象的三大特性之一简单来说封装就是将对象的属性和方法有机结合隐藏内部实现细节仅对外提供接口用于交互。就像电脑主机内部封装了各种硬件的实现细节仅提供开机按钮、鼠标和键盘等让用户和计算机交互。 如何隐藏内部实现细节呢C 提供了三个访问限定符public、private、protected。 public修饰的成员可以在类外访问private和protected修饰的成员不能在类外访问。 class的默认访问权限为privatestruct为public。
3. 使用习惯
成员函数定义习惯
第一种是成员函数的声明和定义都在类中。
class person
{
public:void print(){...}
private:int age;char name[10];
};需要注意的是这种方式的成员函数定义在类中编译器可能会将其当作内联函数处理。
另一种则是成员函数的声明在类中类在头文件声明定义体在类外cpp文件。一般建议使用这种方式。
//person.h
class person
{
public:void print();private:int age;char name[10];
};//person.cpp
void person::print()//注意要加 person::
{...
}一个类就是一个新的作用域事实上C 中一对大括号就是一个域类的所有成员都在类的域中因此在类外定义类的成员函数时函数名前要加类名::。
成员变量命名习惯
一般会给变量名加个前缀或后缀用于区分成员变量和成员函数形参。
例子
class person
{
public:void init(int age, char name[]){...}
private:int _age; //或 mAgechar _name[10]; //或 mName
};三、对象
1. 基本概念
简单来说类是对一类事物的抽象描述只是一个声明不占物理空间。而类的对象就是类的一个实例化是真实存在在内存空间的。
2. 类对象的存储规则
一个类对象在内存中只会存储它的成员变量成员函数则是放在公共代码区供类的所有对象使用。
那么如何计算sizeof类对象的大小呢 事实上类对象的大小等价于类的大小因为sizeof是根据类型确定大小的。 而类对象中只存储它的成员变量因此只需计算类的所有成员变量所占空间的大小即可。 与 C 语言中计算结构体的大小相同计算类的大小也要考虑内存对齐的规则具体可以参考这篇文章传送门
另外空类比较特殊包括没有成员变量的类因为成员函数是存在公共代码区的不参与类大小的计算空类的大小不是 0编译器会给空类 1 个字节来唯一标识这个类的对象因此空类的大小是 1 。
四、this 指针
1. 基本概念
在对象调用成员函数的时候编译器会自动给函数传递对象的地址当作被调函数的一个指针形参这个指针就叫做this指针。该指针用于在成员函数中访问对象的成员变量。由上文可知对象只会存储自己的成员变量成员函数时放在公共代码区的 事实上编译器给每个非静态的成员函数都隐藏了一个this指针参数。相比于 C 语言调用成员函数时我们不用自己传递对象的地址编译器会帮我们完成。
2. 注意事项
this指针本质是一个常量指针不能修改指向。
由于this指针是对象调用成员函数时成员函数隐藏的一个指针形参所以this指针的作用域是成员函数内部。
对象调用成员函数时对象的地址作为实参传递给this形参。而作为一个形参this指针应当存在函数栈帧中有的编译器为了提高效率也会把this指针存在寄存器。
3. 经典习题
//1.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void Print(){cout Print() endl;}
private:int _a;
};int main()
{A* p nullptr;p-Print();return 0;
}本题结果为正常运行。
在本题中对象地址为空所以对象调用成员函数的时候传给成员函数this形参的是空指针。由于成员函数是存在公共代码区的而不是存在对象中所以对象地址为空并不影响调用成员函数。本题的成员函数内部并没有对this形参的解引用因此不存在对空指针解引用的问题所以程序正常运行。
tips程序里有空指针编译是不会报错的最多就是警告。所以我们写代码如果不小心对空指针解引用编译是不会报错的但是运行程序的时候就会崩溃。
//2.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void PrintA(){cout _a endl;}
private:int _a;
};int main()
{A* p nullptr;p-PrintA();return 0;
}本题结果为运行崩溃。
本题与上题的唯一区别在于本题的成员函数内部访问了对象的成员变量因此存在对this指针的解引用。而对象的地址为空所以传给成员函数的this形参是空指针因此出现了对空指针解引用的行为程序运行崩溃。
4. 常见面试题
综上我们就能回答两个常见的面试题。
this指针存在哪里 this指针作为成员函数隐藏的形参存在函数栈帧中也有可能存在寄存器。
this指针可以为空吗 可以但是成员函数内不能访问对象的成员变量即不能对this指针解引用。