C++初阶篇----类与对象上卷

2024-03-02 13:36
文章标签 c++ 对象 初阶 上卷

本文主要是介绍C++初阶篇----类与对象上卷,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 引言
  • 1.面向过程和面向对象初步认识
  • 2.类的引入
  • 3.类的定义
    • 3.1声明与定义全部放在类体中
    • 3.2声明与定义分离
  • 4.类的访问限定符及封装
    • 4.1访问限定符
    • 4.2封装
  • 5.类的作用域
  • 6.类的实例化
    • 类是对对象进行描述
    • 一个类(一个类型变量)可以实例化出多个对象
  • 7.类对象模型
    • 7.1类对象的大小
    • 7.2类对象的存储方式
    • 7.3结构体内存对齐规则
  • 8.`this` 指针
    • 8.1 this指针的引出
    • 8.2 this指针的特性
  • 总结:

引言

在面向对象编程(OOP)中,类(Class)和**对象(Object)**是两个核心概念。
简单来说,**类定义了对象的模板,而对象是根据类创建的具体实体**。例如,假设有一个类叫做Car,描述了汽车的属性(如颜色、品牌、型号)和行为(如加速、减速、转向)。那么根据这个类,我们可以创建多个具体的汽车对象,每个对象都有自己的属性和行为,但都基于相同的类模板。

在面向对象编程中,程序主要由对象组成,每个对象都是一个实例,具有特定的属性(成员变量)和行为(成员函数)。类则用来定义对象的模板,描述了一类对象共同的属性和行为。

1.面向过程和面向对象初步认识

面向对象编程(OOP)是一种以对象为中心的编程范式,它将数据和操作数据的方法封装在对象中,使得对象可以通过方法与其他对象进行交互。在面向对象编程中,程序的设计和实现是围绕着对象的概念展开的,强调对象之间的交互和继承关系,以及多态性的特性。

面向过程编程(POP)是一种以过程为中心的编程范式,它将问题分解为一系列的步骤或过程,然后按照顺序执行这些步骤来解决问题。在面向过程编程中,数据和操作数据的方法是分开的,程序的设计和实现是围绕着函数或过程的概念展开的,强调按照步骤执行任务。

C语言是面向过程的,关注的是过程,分析求解问题
而C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成

2.类的引入

相较于C语言,结构体中只能定义变量,而在C++中,结构体内不仅可以定义变量,还可以定义函数并在内部嵌套调用
如,C语言栈的实现

#include<iostream>using namespace std;
typedef int DataType;
struct Stack
{//初始化函数void Init(size_t capacity=5){_array = (int*)malloc(sizeof(int) * capacity);_capacity = capacity;_size = 0;}void Push(const DataType& data){_array[_size] = data;_size++;}DataType Top(){return _array[_size - 1];}void Destory(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}//成员变量DataType* _array;size_t _capacity;size_t _size;
};int main()
{Stack s;s.Init();s.Push(1);s.Push(3);s.Push(2);cout << s.Top() << endl;s.Destory();return 0;
}

在这里插入图片描述
而在C++中,结构体的定义,更习惯用 class 关键字来替代

3.类的定义

class name
{//成员函数//成员变量};

class 为定义类的关键字,name为类的名字
类的定义方式有俩种

3.1声明与定义全部放在类体中

若成员函数在类中定义,那么编译器可能会当作 内联函数来处理
在这里插入图片描述

3.2声明与定义分离

类声明放
在这里插入图片描述

4.类的访问限定符及封装

4.1访问限定符

C++实现封装的方式:类与对象的属性与方法结合在一起,设置访问权限的选择性将其接口提供外部使用
在这里插入图片描述

  1. public修饰的成员在类外可以直接被访问
  2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为private,struct为public(因为struct要兼容C)

4.2封装

在面向对象的三大特性中(封装、继承、多态),主要研究类的封装特性,在类和对象阶段
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来
和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。

5.类的作用域

在C中,结构体的定义等价于一个变量的定义,而在C++中类的定义形成了一个新的作用域

C中有全局和局部,static静态
而C++中则形成了一个新的作用域,就好比之前,一块土地有公工区域(公共管理),和非公共区域(无人管理),然后类的定义,开始出现,私人住宅(别人允许你访问,那么便可以做客参观)

在类体外定义成员时,需要标识符 ::作用域操作符指明

void name::fun() 
{//…………
}

6.类的实例化

用类类型创建对象的过程,称为类的实例化

类是对对象进行描述

定义一个类,并没有分配实际的内存空间来存储它

注:类当中的成员函数也没有空间? 类成员函数在定义后,就有了固定的存放位置,当创建类的实例化,并不会重复开辟成员函数的空间

一个类(一个类型变量)可以实例化出多个对象

多个类,分别占用实际的物理空间,储存类成员变量
类比,实例化出对象就像在现实中使用建筑设计图建造出房子,类就是设计图,房子就是实例化
在这里插入图片描述

7.类对象模型

7.1类对象的大小

类对象的大小取决于其成员变量成员函数

1.成员变量的大小:类中的每个成员变量都占用内存空间。基本数据类型(如int、float等)通常占用固定大小的内存空间,而对象、指针或其他用户自定义类型的大小取决于其内部包含的成员变量。
2.对齐规则:在内存中,数据通常按照特定的对齐规则存储,以提高访问速度。对齐规则可以导致成员变量之间存在一些额外的空隙,以保证每个成员变量从正确的内存地址开始。对齐规则通常由编译器和目标平台决定。
3.继承和虚函数:如果类继承自其他类,或者包含虚函数,那么额外的内存空间可能会用于存储指向虚函数表的指针(对于包含虚函数的类)或基类的成员变量(对于派生类)。

如:

//前面所创建的Stack的类与Stack1比较
class Stack1
{int x;int y;int z;
};int main()
{cout << sizeof(Stack) << endl<<sizeof(Stack1)<<endl;
}

在这里插入图片描述

7.2类对象的存储方式

类对象包含类的各个成员
在这里插入图片描述
每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。

代码只保存一份,在对象中保存成员函数的地址
只保存成员变量,成员函数存放在公共的代码段

结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象

7.3结构体内存对齐规则

对齐规则和C语言中的结构体对齐规则是一样

  1. 第一个成员在与结构体偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8
  3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

8.this 指针

8.1 this指针的引出

问题:当俩个同类型的类实例化,调用同一个成员函数,编译器是怎么分辨出,是哪一个面向对象调用函数?

如:

//引用之前所定义的Stack 的类
int main()
{Stack d1;Stack d2;d1.Init();d2.Init();//~~~~return 0;
}
这里调用Init初始化,怎么分辨出是d1,还是d2调用?
这就是this指针的作用了> 在C++中,this指针是一个特殊的指针,它指向当前对象的地址。它是每个非静态成员函数的隐式参数。当你在一个**成员函数内部引用类的成员变量或者调用其他成员函数**时,编译器会自动地插入this指针。

实现的底层逻辑:
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

8.2 this指针的特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
    this形参。所以对象中不存储this指针。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
    递,不需要用户传递

在这里插入图片描述

总结:

C++中通过类可以将数据 以及 操作数据的方法进行完美结合,通过访问权限可以控制那些方法在类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。

这篇关于C++初阶篇----类与对象上卷的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/766298

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

2024/9/8 c++ smart

1.通过自己编写的class来实现unique_ptr指针的功能 #include <iostream> using namespace std; template<class T> class unique_ptr { public:         //无参构造函数         unique_ptr();         //有参构造函数         unique_ptr(