自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(87)
  • 收藏
  • 关注

原创 MYSQL 架构

此外,所有的内置函数(如日期、时间、数学和加密函数等)和所有跨存储引擎的功能(如存储过程、触发器、视图等)也都在Server层实现。存储引擎层是MySQL架构中的底层部分,主要负责数据的存储和提取。不同的存储引擎具有不同的特点和适用场景,用户可以根据实际需求选择合适的存储引擎。MySQL支持多种存储引擎,用户可以根据不同的需求选择最适合的引擎。优化器会考虑多种因素,如表的连接顺序、索引的使用等,以生成最高效的执行计划。MySQL以其高度优化的存储引擎而闻名,可以处理大量的并发请求,并提供高效的查询性能。

2024-12-22 19:00:53 840

原创 选择排序和冒泡排序

时间复杂度:O(n^2)

2024-12-22 18:59:00 99

原创 C++ 中面向对象编程如何处理对象的状态存储与恢复

虽然析构函数主要用于释放资源(如动态分配的内存、文件句柄等),但它也可以作为对象生命周期结束时的“清理”阶段,尽管它通常不直接参与对象状态的恢复。总之,在C++中面向对象编程中处理对象的状态存储与恢复需要综合考虑多个方面,包括成员变量的管理、构造与析构函数的设计、拷贝构造函数与赋值运算符的实现、序列化与反序列化的支持以及可能的设计模式应用等。在某些情况下,程序员可能需要手动管理对象的状态,例如通过提供saveState()和restoreState()方法,这些方法内部实现状态的序列化和反序列化。

2024-12-22 18:22:43 466

原创 C++中如何处理对象的创建与销毁的时机

清理方法:在Java中,虽然没有显式的析构函数,但你可以使用finalize()方法(不推荐,已被弃用),更好的方法是使用try-with-resources语句或显式的close()方法(例如在I/O操作中)。在对象的构造函数中获取资源,在析构函数中释放资源。在一些语言(如C++)中,或者在使用对象池等技术时,你可能需要显式地销毁对象。使用智能指针:在C++中,智能指针(如std::unique_ptr和std::shared_ptr)可以自动管理动态分配的内存,减少内存泄漏的风险。

2024-12-22 18:21:35 441

原创 C++中处理对象的状态变化

封装是面向对象编程的基本原则之一,它通过将对象的状态(属性)和行为(方法)封装在一个类中,并控制对状态的访问,从而保护对象的状态不被随意修改。在C++中,处理对象的状态变化通常涉及多个方面,包括封装、观察者模式、状态模式、事件系统等。观察者模式是一种设计模式,用于在对象状态发生变化时通知并更新其依赖的对象。状态模式允许对象在其内部状态改变时改变它的行为。每个状态都被封装在一个类中,并且对象的行为委托给当前状态对象。以上几种方法可以帮助你在C++中处理对象的状态变化,根据具体的需求和场景选择合适的方法即可。

2024-12-22 18:02:04 238

原创 C++实现工厂模式

工厂模式的好处是它将对象的创建逻辑封装在工厂类中,客户端代码只需要调用工厂方法并传入必要的参数就可以获得所需的对象,而不需要知道具体的实现细节。工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个。3.定义一个工厂类:这个类包含了一个静态方法(有时也可以是非静态的),用于返回抽象产品类的一个实例。4.创建具体工厂类:这些类实现了工厂类中定义的静态方法,并返回具体产品类的实例。2.创建具体产品类:这些类实现了抽象产品类中声明的接口。

2024-12-22 17:59:31 143

原创 C++ 中面向对象编程处理异常

在类的构造函数中,如果初始化失败,通常会抛出异常。在析构函数中也要小心,如果析构函数抛出异常,可能会导致程序的终止(因为正在处理一个异常时不能再抛出另一个异常)。通过合理设计类的构造和析构,利用多态支持,实现异常类继承,以及确保资源管理的最佳实践,可以提高程序的健壮性和可维护性。C++ 支持多态,因此可以定义一个基类异常,然后在派生类中实现具体的异常。设计类和函数,保证在异常发生时对象状态的一致性,例如采取备份策略,进行必要的 rollback。清晰地在文档中说明哪些函数可能抛出异常以及抛出的异常类型。

2024-12-13 22:09:14 378

原创 C++ 中面向对象编程如实现数据隐藏

虽然C++没有像Java那样的接口概念,但可以通过将类中的函数声明为纯虚函数(pure virtual function)来创建抽象基类。抽象基类不能被实例化,但可以作为接口来使用,派生类必须实现这些纯虚函数。通过抽象基类,可以隐藏具体的实现细节,只暴露接口给外部使用。

2024-12-13 22:06:39 390

原创 C++ 中多态性在实际项目中的应用场景

然后,可以创建不同的派生类如Button、Label、TextBox等,分别实现这些函数以处理不同类型的UI组件的绘制和用户交互。这样,就可以使用基类指针或引用来对不同类型的文件进行统一的操作,提高了代码的复用性和可维护性。在算法实现中,多态性可以用于实现不同的算法策略。然后,可以创建不同的派生类如StrategyA、StrategyB等,分别实现各自的execute()函数以执行不同的算法。C++中的多态性是面向对象编程中的一个核心概念,它允许我们在使用基类指针或引用的情况下,调用派生类对象的特定方法。

2024-12-13 22:05:04 653

原创 C++ 中的运算符重载

运算符重载是C++中的一种特性,它允许开发者为自定义类型定义或改变标准运算符的行为。通过运算符重载,你可以使得用户定义的类像内置类型一样使用运算符,比如加法、减法、赋值等。运算符重载可以通过全局函数或类成员函数来实现。

2024-12-13 22:04:05 227

原创 纯虚函数和抽象类在面向对象编程中的意义

例如,你可以添加新的图形类型,而无需修改现有的代码。假设你有多个图形类,比如Circle、Rectangle和Triangle,你可以定义一个包含纯虚函数的抽象类,如Shape,其中包含一个draw()方法。这意味着基类规定了一组必须实现的方法,而具体的实现由派生类负责。通过继承,派生类可以重用基类的代码,同时实现特定的功能。通过定义通用的接口,可以根据不同的上下文条件选择和替换具体实现,从而增强代码的灵活性。这样,如果你有一个Shape类型的指针,你可以调用draw()方法,而无需知道具体的图形是什么。

2024-12-09 21:00:00 321

原创 纯虚函数和抽象类

这意味着这个函数没有提供具体的实现,任何继承这个基类的派生类都必须提供这个函数的实现,否则它们也会变成抽象类,无法实例化。抽象类的主要目的是为派生类提供接口规范,确保派生类实现基类中定义的接口。通过定义抽象类,可以确保所有派生类实现特定的功能,促进代码的可维护性和扩展性。你不能直接创建Base类的对象,同时任何派生类必须实现show(),否则它们也会成为抽象类。在这个例子中,AbstractClass是一个抽象类,因为它包含了一个纯虚函数pureVirtualFunction()。

2024-12-09 20:57:59 186

原创 C++中的多态及其好处

在C++中,一个函数一旦声明为虚函数,编译器在编译阶段不会为它生成静态类型的调用版本,而是生成虚函数表(vtable),表中存放与此函数同名、同参数、同返回值的虚函数的地址。多态性(Polymorphism)是面向对象程序设计的一个重要特征,它指的是同一种类型的对象在不同的情况下表现出不同的行为。在C++中,多态性具体表现为一个函数名可以有多种函数功能的定义,即在不同的情况下调用同一个函数,可以执行不同的功能。当需要添加新的子类时,不需要修改现有的代码,只需要在新子类中实现相应的方法即可。

2024-12-08 13:39:39 243

原创 C++中的继承性及其好处

通过继承,可以在已有类的基础上创建新的类,新类可以继承父类的成员变量和成员函数,同时还可以添加自己的新成员。比如,在一个电商系统中,有一个商品类作为父类,后来需要添加一种特殊的商品类型,如限时折扣商品。例如,在一个动物分类系统中,可以创建一个动物基类,然后派生出哺乳动物类、鸟类、爬行动物类等子类,再进一步派生出具体的动物种类子类,如狗类、猫类、麻雀类、蛇类等。如果多个类具有相同的属性和行为,通过继承可以将这些共同的部分提取到父类中,子类只需要定义自己特有的属性和方法,从而减少了代码量,提高了开发效率。

2024-12-08 13:36:52 838

原创 C++中的封装性

封装性是面向对象编程中的一个重要特性,它将数据和操作数据的方法封装在一个类中,使得类的内部实现细节对外界隐藏起来,只通过特定的接口与外界进行交互。例如,如果一个类的内部数据存储方式从数组改为链表,只要公共的方法(如获取数据、设置数据等)的行为不变,外部使用这个类的代码就不需要进行任何修改,大大提高了代码的可维护性。例如,如果一个类的内部使用了特定的数据结构来存储数据,外部代码不知道这个数据结构的具体实现,就不会错误地直接操作这个数据结构,从而避免了可能导致的错误。

2024-12-06 22:51:08 577

原创 静态链接和动态链接的特点

节省磁盘空间和虚拟内存‌:动态链接可执行文件比功能相同的静态链接可执行文件的体积小,因为它能够节省磁盘空间和虚拟内存,因为函数库只有在需要时才被映射到进程中‌。静态链接的每个可执行文件都有自己的一份函数库的拷贝,而动态链接的所有可执行文件共享一个函数库的拷贝,从而节省内存‌。所有动态链接到某个特定函数库的可执行文件在运行时共享该函数库的一个单独拷贝,这有助于减少内存的使用‌。动态链接解决了静态链接中模块更新困难的问题,因为模块是独立的,更新时不需要重新编译整个程序‌。运行时不需要动态加载库,加载速度较快。

2024-12-06 22:47:01 382

原创 显示类型转换的风险

显式类型转换(如强制类型转换)指的是程序员明确指定要将一个数据类型转换为另一个数据类型。如果类型之间不兼容,强制转换可能导致未定义行为。例如,将一个派生类指针强制转换为基类指针时,如果没有正确的类型信息,程序在运行时可能会崩溃。使用强制类型转换可能使代码更难以阅读和理解,因为读者可能需要追踪不同类型之间的关系。如果强制转换导致了运行时错误,追踪问题的来源可能会比较困难,特别是在大规模代码库中。强制类型转换可能导致数据丢失,比如将浮点数转换为整数时,会丢失小数部分。

2024-12-06 22:43:37 182

原创 隐式类型转换

隐式转换有时候会导致不直观的行为,比如当较小类型赋值给较大类型时,某些特定条件下可能隐含未预期的结果。在进行混合数据类型的运算时,例如整数与浮点数相加,整数会被隐式转换为浮点数以进行运算。频繁的隐式转换可能导致额外的性能开销,尤其是在循环或大量运算中,可能影响程序性能。当将一个实际参数传递给一个期望不同类型形参的函数时,编译器会进行隐式转换。例如,将一个浮点数转换为整数时,可能会丢失小数部分,从而导致不准确的结果。将某种类型的值赋给另一种类型的变量时,如果可能,编译器会自动进行转换。

2024-12-06 22:41:49 206

原创 函数重载及其原理

1.实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。C++支持函数的重载,因此编译器需要在编译阶段对函数名进行修饰,生成唯一的函数名以区分不同的函数。

2024-12-02 21:34:28 1425

原创 c++内存对齐

CPU每次寻址都是要消费时间的,并且CPU 访问内存时,并不是逐个字节访问,而是以字长(word size)为单位访问,所以数据结构应该尽可能地在自然边界上对齐,如果访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存访问仅需要一次访问,内存对齐后可以提升性能。现代CPU从内存读取数据时,通常是以块为单位进行的。有些CPU可以访问任意地址上的任意数据,而有些CPU只能在特定地址访问数据,因此不同硬件平台具有差异性,这样的代码就不具有移植性,如果在编译时,将分配的内存进行对齐,这就具有平台可以移植性了。

2024-12-01 19:30:00 338

原创 右值引用和移动语义

c++11 添加了右值引用,却不能左值初始化右值引用,在一些特定的情况下免不了需要左值初始化右值引用(用左值调用移动构造),如果想要用左值初始化一个右值引用需要借助std::move()函数。在 c++用对象初始化对象时会调用拷贝构造,如果这个对象占用堆内存很大,那么这个拷贝的代价就是非常大的,在某些情况,如果想要避免对象的深拷贝,就可以使用右值引用进行性能的优化。例如,在容器元素的插入、删除和返回操作中,通过移动语义可以避免不必要的数据复制和额外的内存分配开销,从而提高容器的性能和效率。

2024-11-30 16:28:38 1682

原创 自动类型推导(auto 和 decltype)

decltype 关键字用于查询表达式的类型,而不实际计算该表达式。这对于某些类型需要在编写代码时获得,但不想编写冗长的类型名称尤其有用。在C++中,自动类型推导使得编程变得更加灵活和简洁。auto 关键字允许编译器根据初始化表达式的类型来自动推导变量的类型。这减少了代码中的冗余,并且使得类型推导更加清晰和易于维护。在使用auto时,如果上下文不明确,编译器可能会推导出你不期望的类型,尤其是在指针和引用的使用上。auto 只能在变量声明时使用,不能作为返回类型(但可以与尾返回类型结合使用)。

2024-11-30 16:26:10 227

原创 volatile 关键字与 const 关键字的区别

volatile 和 const 也可以结合使用,例如 const volatile int,这表示变量的值可能会被外部因素改变,但在代码中不能被修改。变量的值可以随时被改变,尽管你在代码中没有显式地修改。用于指示变量的值可能会在程序的任意时刻被外部因素改变,例如硬件、另一个线程或信号处理程序。通常用于多线程环境、处理硬件寄存器、信号处理程序或其他可能在程序流之外修改的值。这向编译器传达了一个信息,它可以进行某些优化,因为它知道该变量不会被意外修改。变量的值在初始化后就不可再修改,尝试修改会导致编译错误。

2024-11-29 16:28:49 212

原创 在 C/C++ 中,volatile 关键字

在 C/C++ 中,volatile 关键字用于告诉编译器一个变量的值可能会在程序的任何时刻被外部因素改变,因此编译器不应该优化对这个变量的访问。但对于 volatile 声明的变量,编译器会强制每次访问该变量时都进行实际的内存读写,而不是使用寄存器中的缓存值。使用 volatile 可以确保一个线程对该变量的修改能被其他线程立即看到,尽管它并不能替代适当的线程同步机制。在嵌入式编程中,通常会用 volatile 来描述对硬件寄存器的访问,因为这些寄存器的值可能会被硬件事件改变。

2024-11-29 16:26:58 420

原创 函数对象与普通函数的区别

在这个例子中,MyFunctor()创建了一个临时的函数对象实例,并将其作为参数传递给std::for_each算法。函数对象:作为类实例,可以利用C++的类型系统提供更强的类型安全性。函数对象:通常是一个类(或结构体)的实例,这个类重载了operator(),使得其实例可以像函数一样被调用。总的来说,函数对象在C++中提供了一种灵活且强大的方式来封装和传递可调用行为,它们比普通函数更具封装性和状态管理能力。普通函数:是在命名空间或类中定义的独立函数,具有特定的函数名和参数列表。

2024-11-29 16:25:42 442

原创 C++ 中的函数对象

标准库中的函数对象(也称为函数适配器):如 std::ptr_fun、std::mem_fun、std::negate、std::plus 等,这些通常是模板类或函数模板,用于适配或生成函数对象。在这个例子中,Print 是一个函数对象,通过重载 operator(),它能够在 std::for_each 中被调用,从而遍历并打印 std::vector 中的每个元素。在 C++ 中,函数对象(Function Object)是一种可调用对象,它允许像函数一样被调用,但实际上它可能并不是真正的函数。

2024-11-29 16:23:33 370

原创 C++里的虚继承

基类在采用虚继承时,编译器就会给这个类分配一个vptr(虚指针,32位地址空间占4个字节,64位地址空间占8个字节),要访问虚基类的成员时,就通过查表,虚基类的成员只保留一份,不管谁来访问,就是通过查表,虚表和虚指针都是通过编译器自身维护。虚继承‌是C++中一种特殊的继承机制,用于解决菱形继承问题也就是多继承中的二义性问题。在多继承中,如果多个基类共同继承一个公共基类,那么在派生类中可能会出现数据冗余和访问冲突的问题。由于虚基类的成员只保留一份,从整体来说,虚继承比普通多继承更加节省空间。

2024-11-27 15:35:19 203

原创 C++ 中的多继承

复杂的内存模型:多重继承带来复杂的内存结构,尤其是当多个基类之间有共同的父类时,需要额外处理重复基类对象问题。虚拟继承:使用虚拟继承确保从多个路径继承的同一基类只存在一个实例,从而避免重复实例和二义性问题。为了解决多继承中的二义性问题,可以使用全局作用域解析来明确调用哪个基类的成员。丰富的接口:派生类可以同时调用多个基类中的方法和属性,从而拥有更丰富的接口。二义性问题:当多个基类中有同名的成员时,派生类对象调用这些成员会出现二义性。代码复用:派生类可以继承多个基类,从而重用基类中的代码和功能。

2024-11-27 15:34:05 152

原创 Lambda 表达式的捕获列表‌和返回值类型

一般情况下,不指定 lambda 表达式的返回值,编译器会根据 return 语句自动对到返回值类型,但是需要注意的是,lambda 表达式不能通过列表初始化自动推导出返回值类型。[this] 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。[=] 捕获外作用域中的所有变量,按照值捕获,拷贝过来的副本在函数体内是只读的。[=,&a] 按值捕获外作用域中的所有变量,并且按照引用捕获外部变量a。[bar] 按值捕获 bar 变量,不捕获其他变量。

2024-11-25 20:47:26 160

原创 C++ 中的 Lambda 表达式

Lambda是c++11中引入的语法特性,允许开发者定义匿名函数。Lambda表达式可以看作是一个简化的函数对象,它提供了一种便捷的方式来定义和使用函数,特别是在需要传递函数作为参数或者定义临时函数时非常有用‌。其中 capture 是捕获列表,params 是参数列表,ret 是返回值类型,body是函数体。Lambda表达式可以作为参数传递给其他函数,特别是在STL算法中作为谓词使用,实现更加灵活的功能‌4。Lambda表达式与STL容器、智能指针等一起使用,可以简化代码编写,提高代码的可维护性‌4。

2024-11-25 20:45:54 242

原创 C++ 中的类型别名和 using 声明及其如何使用。

类型别名允许为已存在的类型创建一个新的名称,这在处理复杂的类型表达式时特别有用,可以使代码更清晰、更易于理解。命名空间‌:在引入命名空间中的标识符时,using可以避免全局命名空间的污染,而typedef则没有这个优势。依赖名称查找‌:在使用多个同名的别名时,using会导致编译错误,而typedef不会报错但可能会导致歧义。using声明不仅用于定义类型别名,还可以用来引入命名空间中的标识符,或者明确指定类成员的访问方式。模板别名‌:using可以用于模板别名,而typedef无法用于模板别名。

2024-11-24 17:52:25 328

原创 C++ 中的模板特化和偏特化

函数模板偏特化‌:当函数模板的某些参数类型被指定为特定类型时,可以提供偏特化的实现。偏特化分为‌函数模板偏特化‌和‌类模板偏特化‌。模板特化分为‌函数模板特化‌和‌类模板特化‌。类模板偏特化‌:对于类模板,当某些参数类型被指定为特定类型时,可以提供偏特化的实现。C++中的模板特化和偏特化是C++模板编程中的两种重要技术,用于在特定情况下提供更优化的代码实现。通过特化和偏特化,可以在不同情况下使用不同的实现方式,增加代码的灵活性和适用性。这里,当第二个参数为int时,使用偏特化的ClassA‌。

2024-11-23 18:57:21 342

原创 C++ 中的智能指针

std::weak ptr 没有重载操作符*和->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视shared ptr 中管理的资源是否存在。共享智能指针ap,bp对A\B实例对象的引用计数变为2,在共享智能指针离开作用域之后引用计数只能减为1,这种情况下不会去删除智能指针管理的内存,导致A,B的实例对象不能被析构,最终造成内存泄漏。共享智能指针对象sp1和sp2管理的是同一块内存,因此最终打印的内存中的结果是相同的,都是520。

2024-11-22 19:32:53 1547

原创 移动语义和拷贝语义的区别

移动语义通常在以下情况下非常有用:当对象包含大量资源(如动态分配的内存、文件句柄等)时,进行拷贝操作可能会非常昂贵,而移动语义可以高效地将资源转移,避免不必要的复制。当一个对象被初始化或赋值给另一个对象时,如果存在移动构造函数和移动赋值运算符,并且右值可以被移动,编译器会优先调用移动构造函数和移动赋值运算符进行移动操作。例如:在 C++中,使用 std::vector 的移动构造函数可以快速地将一个 vector 对象的内容转移到另一个 vector 对象中,而不需要逐个复制元素。

2024-11-22 19:27:04 461

原创 右值引用是什么?如何使用右值引用实现移动语义?

左值引用(lvalue reference)和右值引用(rvalue reference)是 C++ 中用于管理对象生命周期和优化性能的关键概念。右值引用是引入 C++11 的新特性,主要用于实现移动语义,以减少不必要的复制操作。右值引用 允许我们通过 && 语法来引用这些右值,以便表明我们打算“移动”它们的资源,而不是复制。使用右值引用可以实现移动构造函数和移动赋值运算符,允许资源的转移而不是复制,从而提高程序的性能。右值引用 是用于引用临时对象的引用类型,以 && 表示。

2024-11-22 18:48:00 336

原创 C++ 中的移动语义

C++ 中的移动语义是一种优化技术,旨在通过转移资源所有权而非复制资源来提高程序的效率。它主要通过引入右值引用(rvalue references)和移动构造函数、移动赋值运算符来实现,从而减少不必要的内存分配和复制操作,尤其是在处理动态分配内存的对象时。性能提升:移动语义允许临时对象(右值)中的资源(如动态分配的内存)被“移动”到另一个对象,而不是创建一个新的副本。更加安全的资源管理:移动语义确保对象在转移资源后,原对象不要再访问这些资源,从而防止了悬空指针和资源泄漏的问题。

2024-11-22 18:46:15 135

原创 初始化列表和在构造函数体内赋值的区别

语法:ClassName(Type1 arg1, Type2 arg2) : member1(arg1), member2(arg2) { }可以初始化 const 变量和引用成员,这是唯一的初始化方式,因为 const 和引用必须在对象创建时就被赋值。赋值的顺序是按照代码中的顺序,但这可能与成员声明的顺序不同,这在依赖于成员的顺序时可能造成问题。在构造函数参数列表后面,使用冒号 : 进行初始化,成员变量在对象创建时直接初始化。更高效,因为可以直接初始化成员,避免了默认构造和后续赋值的开销。

2024-11-20 20:25:55 150

原创 C++ 中的初始化列表

在 C++ 中,初始化列表是一个用于构造函数的特殊语法,允许在构造对象时直接初始化成员变量。它的语法形式是在构造函数的参数列表后面使用冒号 :,接着是成员变量的初始化。通过初始化列表,类的成员可以在构造时直接构造,而不是先默认构造再赋值,这样可以避免不必要的构造和赋值操作,特别是当成员是复杂类型时,这种效率提升是显著的。成员变量的初始化顺序是按照它们在类中声明的顺序,而不是在初始化列表中出现的顺序。如果类中有常量成员(const),则必须使用初始化列表进行初始化,因为常量成员必须在其创建时就被赋值。

2024-11-20 20:22:46 120

原创 友元的作用

简化代码:在需要复杂数据交互时,可以通过友元函数或友元类简化实现,例如可以直接访问对象的内部状态,减少了通过 getter 和 setter 方法的需要。封装性降低:友元函数和友元类的过度使用会导致类的封装性下降,因为它们破坏了类内部状态的私密性。在设计时应谨慎选择。增加代码依赖:友元关系增加了代码之间的依赖性,如果一个类的实现发生改变,可能导致使用此友元的其他类也需要修改。设计考虑:考虑是否可以通过公共接口满足需求,尽量减少使用友元,以保持良好的设计原则。

2024-11-18 22:39:18 241

原创 C++ 中的友元函数和友元类

在这个示例中,BoxManager 类被声明为 Box 的友元。这样,BoxManager 的成员函数可以访问 Box 类的私有成员 width。在上述代码中,Box 类有一个私有成员 width,但 printWidth 函数被声明为友元函数,因此它可以直接访问 width。友元函数是一个被特定类所声明为"友元"的普通函数,这使得该函数可以访问该类的私有和保护成员。printBoxWidth 函数直接访问 Box 的私有数据,不需要通过公共接口。友元类允许一个类访问另一个类的私有和保护成员。

2024-11-18 22:38:09 221

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除