- 博客(72)
- 收藏
- 关注
原创 C++面向对象--多态
封装是面向对象编程的重要概念之一,它提供了一种将数据和操作封装在一起的方式,以实现数据隐藏、接口抽象、数据有效性和代码复用等优势。在图形图像处理领域,多态性允许我们定义通用的图形接口,如绘制(draw)方法,然后在不同的图形类中实现具体的绘制逻辑。通过多态性,我们可以将不同的策略实现为基类的不同子类,从而实现灵活的算法选择。通过将成员函数声明为类的成员,我们可以实现对数据的封装和控制访问方式。C++中多态性是面向对象编程中的一个重要概念,它允许我们在使用基类指针或引用的情况下,调用派生类对象的特定方法。
2024-12-15 13:52:58
369
原创 C++多态性
函数重写(覆盖):定义:子类重新定义父类中有相同名称,返回值和参数的虚函数,主要在继承关系中出现。父类中的fun函数是虚函数,子类中有返回值,名字 参数 相同的fun函数,那么子类中的fun函数(无论加不加virtual)都是虚函数基本条件:重写的函数和被重写的函数必须都虚(virtual)函数,并分别位于基类和派生类中重写的函数和被重写的函数,返回值,函数名和函数参数必须完全一致;函数隐藏:子类中只要和父类函数名字相同不是重写,一定是函数隐藏。
2024-12-09 15:58:51
305
原创 纯虚函数与虚函数
纯虚函数是在基类中声明的虚函数,在基类中没有具体的实现,其形式为virtual 返回类型 函数名(参数列表)=0;纯虚函数只有声明,没有函数体。含有纯虚函数的类被称为抽象类,不能被实例化。为派生类提供一个必须实现的接口规范,实现多态性。不同的派生类可以根据自身需求实现纯虚函数,从而在使用基类指针或引用调用函数时,能正确地调用到派生类中具体的实现。
2024-12-08 17:04:45
534
原创 静态链接与动态链接
C语言可执行文件的四个步骤:预处理,编译,汇编,链接。预处理:进行头文件,宏替换等内容编译:将代码转成汇编语音汇编:将汇编语言转成01二进制链接:最后生成可执行文件在链接过程中,有动态链接和静态链接两种。
2024-12-04 14:34:47
275
原创 C/C++类型转换
不如C++风格转换安全:相比于 C++提供的类型转换运算符(如 static_cast, dynamic_cast, const_cast, 和 reinterpret_cast),括号式转换缺乏类型安全性和可读性。例如,如果不注意,可能会在不适当的时候发生精度损失。此外,类的构造函数如果只有一个参数,也可能导致意外的隐式类型转换,这可能会引起程序逻辑错误。此外,强制类型转换也可能会破坏对象的完整性,例如将一个派生类指针强制转换基类时,如果不恰当使用可能会导致错误的行为。在类的构造函数前使用。
2024-12-04 12:47:07
297
原创 C++函数重载,函数重写,函数隐藏
在同一作用域下,相同函数名,函数参数的顺序,类型,个数不同这种情况被称为函数重载函数重载与返回值无关同一作用域:作用域是程序的一个区域,被分为局部作用域,全局作用域,块作用域,类作用域这几种C语言不能重载,C++可以重载,因为在C++编译器会把函数名转换成函数名_参数类型的形式。
2024-12-02 13:26:15
389
原创 C/C++内存对齐
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。
2024-12-01 12:57:40
481
原创 自动类型推导与右值引用移动语义
C++ 中的变量必须是有明确类型的,使用了 auto 关键字以后,编译器会在编译期间自动推导出变量的类型,然后用真正的类型代替 auto 这个占位符,这样我们就不用手动指明变量的数据类型了。使用 auto 类型推导的变量必须马上初始化,以方便编译器进行类型判断。使用auto关键字要注意的几点使用auto关键字必须对变量初始化auto 单独使用时会去掉 const 和引用。auto 用于推导指针时会保留指针所指向类型的 const。
2024-11-30 14:14:23
606
原创 C/C++ 中volatile 关键字
他提示在该关键字之后的变量可能随时发生改变,因此编译后的程序每次需要存储或读取这个变量的时候,告诉编译器对该变量不做优化,都会直接从变量内存地址中读取数据,从而可以提供对特殊地址的稳定访问。如 果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。volatile在编译期和运行期都有用,在运行期:每次用到该变量的值,都从内存中取该变量的值。volatile修饰的变量的可能随时发生变化的,直接从变量内存中读取地址。
2024-11-28 17:41:14
454
原创 C++中的多继承
虚继承可以帮助实现这种设计,使得派生类能够以一种清晰、高效的方式整合多个继承路径的功能,避免因为继承结构复杂而导致的混乱和错误。在 C++ 中,虚继承是一种用于解决多继承中菱形继承问题(也称为重复继承问题)的机制。:在菱形继承结构中,如果没有虚继承,最底层的派生类会包含多个间接基类的副本。菱形继承:若有多个基类有共同的祖先,则会导致数据和方法的重复继承,并且可能重复的构造和析构同一个基类对象。多重继承:如果一个派生类只继承一个基类,称作单继承,如果继承了多个基类,那么就成为多继承。多重继承可以做更多的。
2024-11-27 18:20:56
652
原创 C++ Lambda 表达式
Lambda表达式(也叫lambda函数,匿名函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。[捕获列表][参数列表][可变规则][返回值类型][函数体]其中capture是捕获列表,params是参数列表,ret是返回值类型,body是函数体。捕获列表[]:捕获一定范围内的变量参数列表(): 和普通函数的参数列表一样,如果没有参数参数列表可以省略不写。
2024-11-25 17:26:44
426
原创 C++模版特化和偏特化
特化的含义:所谓特化,就是将泛型搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。函数模板的特化:当函数模板需要对某些类型进行特化处理,称为函数模板的特化。类模板的特化:当类模板内需要对某些类型进行特别处理时,使用类模板的特化。特化整体又分全特化与偏特化。
2024-11-23 20:43:44
521
原创 移动语义和拷贝语义有什么区别?
拷贝语义是一种传统的对象复制方式,进行拷贝操作的时候,会创建一个新的对象,并将原对象的内容复制给新的对象。拷贝语义通常用于需要保留原始的对象,开辟一个新对象去承接靠北,创建一个与原始对象内容相同的副本。在 C++中,拷贝语义通常通过拷贝构造函数和拷贝赋值运算符实现。当一个对象被初始化或赋值给另一个对象时,如果没有定义移动构造函数和移动赋值运算符,编译器会自动调用拷贝构造函数和拷贝赋值运算符进行拷贝操作。
2024-11-23 11:27:02
353
原创 C++11移动语义,右值构造
在 C++ 11 之前,对象之间的赋值(如通过拷贝构造函数或赋值运算符)是通过拷贝的方式进行的。C++11引入的新特性,允许将一个资源从一个对象转移到另一个对象,而不是传统意义上的拷贝操作。有一个类,包含一个数组,在对象拷贝的时候需要将一个资源从一个对象复制到另一个对象,这涉及资源的分配问题,与数据的复制问题,C++11引入了移动语义,将资源直接从一个对象转移到另一个对象,移动语义主要是通过右值引用(&&)来实现的。右值引用可以绑定到将要销毁的对象(即右值),这些对象的值可以被 “窃取”。
2024-11-21 18:17:48
704
原创 C++初始化参数列表
初始化参数列表:跟在构造函数后边,用冒号开头,后边跟着逗号进行分割初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值操作。class Apublic:// 初始化列表private:int id;
2024-11-20 19:26:52
489
原创 C++友元函数与友元类
c++中类具有封装的的隐藏性,只有成员函数才能访问类内的私有成员变量,程序的其他函数没有办法访问私有成员变量。友元函数在类外定义,类内声名的普通函数,为了与普通函数进行区别,在函数名前加上friend关键字,友元函数并不是成员函数,但是友元函数可以访问类内的私有成员变量。友元函数的好处就是提高了程序运行的效率,缺点就是破坏的类的封装性与隐藏性。
2024-11-18 16:52:48
408
原创 C/C++类型转换方式
上行转换(Upcasting):从子类转换为父类。下行转换(Downcasting):从父类转换为子类,且要求父类中至少有一个虚函数(即是多态类)当栈尾的值与链表头的值相同的时候,那就弹出栈尾元素,节点向后移动一位,如果不等,直接返回0;是 C++ 中的一种类型转换操作,专门用于处理多态类型(即包含虚函数的类层次结构)。显示类型转换,不恰当的使用可能会导致问题,不安全转换导致运行失败。可以在运行时对类的类型进行检查,确保类型转换的安全性。最先进栈的最后出栈,栈尾就是链表的最后一个节点。
2024-11-17 18:06:08
369
原创 C++内联函数
【C++】C++中内联函数详解(搞清内联的本质及用法)-优快云博客内联函数在形式上与普通函数结构相同,只是在函数前加上一个inline关键字return a+b;内联函数目的:代替部分 #define 宏定义;使用内联函数替代普通函数的目的:提高程序的运行效率;递归函数不能被设置成内联函数。
2024-11-17 17:41:18
339
原创 C++常量表达式
常量表达式是在编译时期就能计算出结果的表达式,他的值是一个常量,不会改变。例如上述例子,在编译时期就能确定b的值是什么。int a=5;这个例子就不是常量表达式。因为我们只是给a一个初始变量值,在后续代码的编写中还是可以对这个a进行重新赋值的。
2024-11-15 19:18:13
375
原创 C++函数返回值的内存传递过程,虚拟内存
如果在物理内存下,在同一个内存中写入两个程序是不可能的,这会导致程序崩溃,这就需要操作系统为进程分配独立的虚拟地址来进行,各个进程都有自己的地址,互不干扰,这些进程不能访问操作系统的物理内存地址,操作系统会提供一种机制来解决虚拟地址怎么落到物理内存里。对于基本数据类型,返回值通常通过寄存器传递,或者如果返回值较大,可能会通过拷贝一个临时对象来传递。对于引用或指针类型的返回值,返回的是地址,不涉及复制或移动操作。程序中用的地址都是虚拟内存地址,实际上硬件里边的空间是物理内存地址。
2024-11-14 19:01:08
307
原创 C++异常处理机制
例如:如果异常抛出是用的 int 类型 而在外部捕获中 捕获函数是用的char类型进行的捕获那么,该错误就不会被捕获到,而代码也就此终止异常继续往外传。异常是一种处理错误的方式,当一个函数发现自己没有办法处理错误的时候,抛出异常,然函数的直接或者间接的调用者来处理错误。1. 异常会导致程序的执行流乱跳,非常的混乱,这会导致我们跟 踪调试时以及分析程序时,比较困难。异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。1. 先遍历左子树的深度,再遍历右子树的深度。
2024-11-13 20:36:27
434
原创 C++命名空间
在C++中,命名空间(Namespace)是一种将代码组织成逻辑组的机制,用于避免不同代码模块之间的命名冲突。它提供了一个声明区域,在该区域内可以定义各种类型、函数、变量等,并且这些定义的名称在该命名空间内是唯一的。1. 避免命名冲突:不同的库或者代码可能存在相同的变量与函数,命名空间可以将他隔离开,使得同名的实体在各自的空间中有不同的作用域2. 组织代码结构:命名空间有助于将相关的代码组织在一起,提高代码的可读性和可维护性。
2024-11-12 20:14:20
531
原创 C++预处理指令
在代码长度方面:宏代码都会被插入到代码之中,代码长度会增加,函数调用,函数代码只出现在那一个地方,但是需要开辟栈帧造成开销执行速度·,宏定义更快会收到操作符优先级影响宏: #define 机制包括了一个规定,允许把参数替换到文本中在代码中计算一个数的平方的时候可以直接调用,如计算5的平方fun(5)如果计算的是5+1的平方呢,宏不会先计算5+1的和再去计算平方的,而是直接计算,也就是5+1*5+1;这样就与用户所想的计算结果不相同。参数求值方面:参数每次用于宏定义时。
2024-11-09 19:15:10
483
原创 函数模版与类模版
在定义类的时候,加上一个/多个类型参数。在使用类模板时,指定类型参数应该如何替换成具体类型,编译器据此生成相应的模板类。编译器由类模板生成类的过程叫类模板的实例化。由类模板实例化得到的类,叫模板类。函数模板可以重载,只要它们的形参表或类型参数表不同即可。在有多个函数和函数模板名字相同的情况下,编译器如何处理,
2024-11-08 19:35:30
298
原创 new与malloc的区别
在对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数。而malloc/free是库函数,是已经编译的代码,所以不能把构造函数和析构函数的功能强加给malloc/free,所以new/delete是必不可少的。在c++11中我们引入了智能指针这一概念,shared_ptr共享内存指针,循环引用问题在C++中是指当两个或多个对象互相持有对方的引用,导致它们的引用计数永远不会降为零,从而导致内存泄漏的情况。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。
2024-11-07 19:58:23
411
原创 malloc分配内存失败会怎么样
调用operator new 函数(对于数组是operator new[])分配一块足够的内存空间(通常底层默认使用malloc实现,除非程序员重载new符号)以便存储特定类型的对象;new出的空间需要delete释放,malloc申请玩的空间需要free释放。new的返回值不需要强转,malloc的返回值是void*类型的,需要强转。new申请空间不用填具体大小,malloc需要详细具体申请多大空间。new申请空间失败会抛出异常,malloc申请失败会返回为空。不对称的情况:左右子树层数不同。
2024-11-06 19:45:22
461
原创 拷贝构造与复制运算符的区别
因为防止一直递归,因为会一直走拷贝构造形式如template 返回类型 函数名 (参数列表)//函数体//函数模版的申明int main()return 0;T Max(T x, T y) //函数模版的实现x : y);有函数模版也有类模版运用模版可以提高代码的耦合性。
2024-11-05 19:01:55
294
原创 C++面向对象思想
特点函数名与类名相同没有返回值,不写void可以实现函数重载如果自己没有实现构造函数,编译器会自动提供一个默认构造创建对象的时候调用构造函数调用方式//括号法//显示法//隐式转换法。
2024-11-04 20:31:41
277
原创 结构体,联合体与类
联合:各成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权(对该内存的读写),各变量共用一个内存首地址。因而,联合体比结构体更节约内存。联合的大小为其最大成员的大小。结构体的大小:等于所有成员大小之和,还会发生内存对齐的问题。在C++中,结构体中可以包含函数。结构体的默认访问继承权限是公有的。联合说明和联合变量定义的形式为。最大的区别就是在内存利用方面。在c语言中结构体不能包含函数。类的默认访问继承权限是私有的。在c++中有类这一概念。
2024-11-03 17:20:33
281
原创 C/C++字符串存储的方式
c++中字符串有两种存储方式,一种是存储在char[]数组中,一种是存储在c++封装的string类中。在C中也可以使用字符指针来访问一个字符串,通过字符指针指向存放字符串数组的首元素地址来进行访问.在C中,并没有字符串这个数据类型,而是使用。char[]来保存字符串。二叉树的先序遍历根左右。二叉树的后序遍历左右根。
2024-11-02 16:53:29
410
原创 什么是内存泄漏
内存泄漏就是,我们在堆区手动申请的一块内存空间,使用完这块空间,并没有手动释放掉,导致这块空间没有回到内存池中,使得我们的内存找也找不到,也不能继续使用,怎么避免内存泄漏:我们要及时释放动态分配的内存空间。c++11中引入了智能指针这一概念,shared_ptr用来解决内存泄漏的问题。
2024-10-31 16:19:03
323
原创 C/C++内存分区
c++中引入了shared_ptr的共享指针,采用的是RAII思想,是一个内存计数,记录每个对象有几个指针指向,当指向该对象的计数为0的时候,才可以析构该对象,释放内存空间。指针变量没有被初始化。两个指针指向同一块内存,指针与内存使用完毕后,只改变了一个指针的指向,没有改变另一个对象的指向,就会发生内存泄漏的问题。bss段:存储未被初始化的全局变量,和data段一样都属于静态分配,在编译阶段就确定了大小,不释放。stack段(栈空间):主要用于函数调用时存储临时变量的,这部分的内存是自动分配,自动释放的。
2024-10-30 16:23:56
303
原创 C++中指针与引用
排序序列长度为 m+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n))。排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。时间复杂度:O((m+n)log(m+n))。空间复杂度:O(log(m+n))。
2024-10-29 19:16:21
328
原创 递归函数与回调函数
回调函数就是一个通过函数指针调用的函数。它描述的是这样一个过程:一个函数(称为回调函数)作为参数传递给另一个函数(称为调用函数),当满足一定条件或者在某个特定时刻,调用函数会调用传递过来的回调函数。这种机制允许程序员在编写代码时,能够在不同的上下文中重用函数,同时也能实现异步处理、事件驱动编程以及模块间的松散耦合回调函数的特点低耦合性,动态性,可以实现代码的分离和可扩展性。
2024-10-28 20:17:45
394
原创 函数参数传递的方式有哪些
算法题买卖股票的最佳时机贪心算法,找到最优的利润,买进是最低价格,卖出是最高的价格,才能达成最优利润遍历这个数组,首先我们需要找到买进的最低价格,初始变量min_price初始化为int_max就是最大的值,之后调用min 与当前数值取最小值。用当前数与最小值相减,找到最大利润如果发现有值比当前最大值大就进行换最后返回最大利润。基础知识如何使用switch-case语句,有什么注意事项?首先switch中的表达式必须为常量,不能是一个判断形的语句。
2024-10-27 21:09:22
353
原创 C/C++中的基本控制结构
break用于跳出一个循环体或者完全结束一个循环,不仅可以结束其所在的循环,还可结束其外层循环。一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。continue语句的作用是跳过本次循环体中剩下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为只是中止(跳过)本次循环,接着开始下一次循环。当break出现在循环体中的switch语句体内时,起作用只是跳出该switch语句体,并不能终止循环体的执行。当条件为真的时候走if中的,当条件为假的时候,走else中的内容。
2024-10-26 16:06:26
635
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅