自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 个人博客系统自动化测试报告

本项目基于SSM框架实现,包含4个界面:登录界面、博客发表界面、博客列表界面以及博客详情界面。登录后即可查看自己已发布的博客,也可以发布博客,通过使用Selenium定位web元素、对获取到的元素进行操作等,对个人博客系统进行测试,测试的核心内容包括用户登录、博客列表、用户信息、查看全文、详情页内容、发布博客、退出账号等。该博客系统可以实现发布个人博客,记录博客发布日期、时间、标题、博客发布者等信息。Selenium 支持多种主流浏览器,如 Chrome、Firefox、Safari、Edge 等。

2025-03-14 21:45:16 1024

原创 【C++】AVL树

注意:AVL树和下面介绍的红黑树相比于二叉搜索树,节点中多了一个指向双亲结点的指针。_bf就是平衡因子。

2025-03-03 17:30:00 880

原创 【C++】set/multiset/map/multimap

点击了解set点击了解multiset点击了解map点击了解multimap。

2025-03-03 05:30:00 585

原创 【C++】二叉搜索树

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。实现中序遍历那就需要根节点的指针,可是当我们在main函数调用的时候,是在BinarySearchTree类外,_root是类的private成员,只有在类里面才能访问,在类外不能被访问,所以该如何解决这一问题呢?如果找到,那返回节点的指针。

2025-02-09 12:38:55 746

原创 【C++】多态(下)

2、 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。那么我们如何查看d的虚表呢?需要注意的是在单继承和多继承关系中的虚函数表,下面我们去关注的是派生类对象的虚表模型,因为基类的虚表模型前面我们已经看过了,没什么需要特别研究的。菱形继承的对象模型和多继承相似,如果派生类有不是继承的虚函数A,如果继承的基类有虚表指针,那么将虚函数A放到第一个有虚表指针的基类的虚表中。

2025-02-05 17:30:00 1825

原创 【C++】多态(上)

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了 Person。Person对象买票全价,Student对象买票半价。那么在继承中要构成多态还有两个条件:1、 必须通过基类的指针或者引用去调用虚函数2、 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写下面我们来解释虚函数和重写在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。

2025-02-05 07:30:00 675

原创 【C++】继承(下)

1、 很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。2、 多继承可以认为是C++的缺陷之一,很多后来的语言都没有多继承,如Java。3、 继承和组合组合是什么?将一个类(如A)作为成员变量放在另一个类中(如B)public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。组合是一种has-a的关系。

2025-02-03 17:22:37 1152

原创 【C++】继承(上)

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类或子类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类。

2025-02-03 06:00:00 970

原创 【C++】模板进阶

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生增强了代码的灵活性模板会导致代码膨胀问题,也会导致编译时间变长出现模板编译错误时,错误信息非常凌乱,不易定位错误。

2024-12-08 08:00:00 1065

原创 【C++】容器array+类的按需实例化

当没有调用operator[ ]时,编译器不会对它的内容进行很细致的检查,所以就检查不出来。只有调用operator[ ],才会实例化operator[ ],编译器才会细致的检查,因此能检查出来。但容器array的对象,对任意越界读写都能检查出来。

2024-12-06 16:45:00 273

原创 【C++】自主实现反向迭代器

rend:指向第一个元素的前一个位置),第二种是库在实现反向迭代器时所选的位置,因为想让begin/end和rbegin/rend的位置是对称的,我们下面的实现反向迭代器的类也采用第二种方式。本来每个容器都要写一个反向迭代器,但是库里面却是只有一个反向迭代器的类模板,只要给编译器传不同的容器的正向迭代器模板的实例化,编译器就能帮我们实例化出各种容器对应的反向迭代器。

2024-12-06 07:00:00 355

原创 【C++】自主实现优先级队列priority_queue

我们现在加上仿函数,优先级队列的仿函数有缺省值less,表示大堆存储。思路:先不删除堆顶的元素a,将它与堆的最后一个数据b交换位置,再删除a,最后将b不断向下调整。将上面5个函数都写完了,就可以开始使用自主实现的优先级队列了。

2024-12-04 16:30:00 726

原创 【C++】priority_queue优先队列

优先级队列priority_queue的底层是堆,默认情况下,是大堆。我们也可以传仿函数来让priority_queue为小堆下面是默认情况下的priority_queue,为大堆。注意:只是取出来的数据是有序的,但是优先级队列容器内不有序(因为大堆/小堆只是逻辑结构是树,事实上一般是用数组存储的)下面我们想试试让priority_queue为小堆,需要传仿函数先用仿函数,内容后面讲想用仿函数greate,需要包头文件algorithm,这样priority_queue就是小堆。

2024-12-04 07:45:00 1089

原创 【C++】deque(双端队列)介绍

如果满了,就开辟一个大小为N的数组c,在中控指针数组里存放数组c的地址,再将数据从数组c的最前面开始插入。2、 让pos位置所在的数组的个数+1,将该数组位于pos及后面的元素往后挪一个位置,将数据插入到pos位置。如果中控指针数组满了,就扩容,此时如何找第i个值呢?

2024-12-02 17:00:00 979

原创 【C++】自主实现stack/queue

queue实现需要尾插,头删,所以不用vector,因为vector没有提供pop_front函数,可以用erase,但效率较低。但是我们查看库里的stack和queue,它们的缺省值不是vector/list,而是deque,deque是什么?

2024-12-02 08:12:58 347

原创 【C++】自主实现容器list

直接用const修饰begin/end,那就是const/非const对象都能调用begin/end,begin/end的返回值类型是iterator,类iterator对*运算符重载的返回值类型是引用,可读可写,因此这样的话,即使是const对象也能修改内容。问:const修饰的对象x,我们是不想让迭代器的指向修改,还是不想让迭代器指向的内容修改?我们上面的测试都是用list来的,如果list<>中的类型是自定义类型,如下图的A,那我们的遍历也要修改,因为*it是A,A有2个成员变量。

2024-11-29 14:30:00 720

原创 【C++】容器list

不要太使用list的sort,它较vector的sort(实际上sort并不是vector的成员函数,而是algorithm的函数)效率较慢。从x中转移元素,插入到pos位置,因此x的被转移的元素就不会再存在于x了。默认升序(1),如果想要排降序,那就要传仿函数(2)

2024-11-29 07:30:00 250

原创 【C++】自主实现string类

因为end是int类型的,pos是size_t的,不同类型比较时要先转换成同种类型,所以将int转换成size_t,因为size_t是无符号整型unsigned int,它>=0,因此将end转换成size_t类型的临时变量与pos==0相比较,永久成立,因此会死循环(end会变成负数,但是将end转换成size_t类型的临时变量,该临时变量是>=0的)要求:当n<=_size时,string类对象的内容变为_str[0,n],_str[n]=’\0’,即有效的字符个数变为n,不缩容。

2024-11-28 14:00:00 1759

原创 【C++】string(二):遍历+了解vs和g++下string的结构

当浅拷贝时,引用计数++。自主实现的string类大小为12,因为成员变量是char*,size_t,size_t(npos是static成员变量,存放在静态区,不在类中,因此不算npos的大小),在32位平台下都是4字节,经过结构体对齐规则,总大小是12。不是引用,就表示依次取string对象s的元素,拷贝给e,自动迭代,自动判断结束,这时只读。

2024-11-28 06:00:00 799

原创 【C++】string(一)

string的字符串底层一定有表结束的’\0’,因为string的底层就是用C语言的字符数组实现的,C语言的字符串用’\0’作为结束标志。begin()和end()也可以用const修饰,如果有const string,那么该string不能被修改,且const string调用begin()/end()时,返回值类型是const_iterator。它避免了扩容,提高效率。

2024-11-13 16:00:00 1101

原创 【C++】模板(二):类模板

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,是生成具体类的模具,而实例化的结果才是真正的类。问:这个类模板关键就是知道T的类型,我们可以用类模板的实例化,那我们C语言的typedef可以胜任吗?不能,为什么?因为如果我们现在要定义2个栈,一个装int类型的,另一个装double类型的,这就不好写,除非再写一个Stack类,但那样就太麻烦了。但是用类模板实例化就能很好的解决。

2024-11-13 05:00:00 472

原创 【C++】模板(一):函数模板

如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件 (即生成具体类型的代码),那将会方便许多。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。

2024-11-11 15:00:00 1076 1

原创 【C++】内存管理(三):定位new

因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

2024-11-11 07:00:00 369

原创 【C++】内存管理(二):operator new/delete

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数(不是对new和delete的运算符重载),new在底层调用operator new全局函数来申请空间,delete在底层通过 operator delete全局函数来释放空间。因此,如果new的是自定义类型,且new的对象>1,但编译器不会调用析构函数,那么就不会报错,因为不会在开辟的空间前开辟一个4字节的空间存储对象个数。不能,只能从最开始即a点释放,所以报错。

2024-11-05 20:00:00 1010

原创 【C++】内存管理(一):new/delete

在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与 free不会。new失败后会抛异常,不需要我们手动检查。

2024-11-05 15:24:32 1265

原创 【C++】类和对象(十二):实现日期类

因为我们相等<<运算符重载没有返回cout,如果返回了cout,那么第一次cout<<d1后的返回值是cout,那接下来的表达式为cout<<d2<<endl。因为双操作数的操作符,左右的操作数必须和运算符重载函数的形参顺序相同,函数的第一个形参是隐藏的this,第二个才是out。将<<运算符重载的声明写在类中,<<运算符重载需要有参数:cout(类型是ostream),为什么?先知道哪个的日期较大/较小,让较小的日期进入循环,每循环一次,较小的日期+1,等到两日期相等,看循环的次数就知道两日期相差几天。

2024-11-03 14:00:00 703

原创 【C++】类和对象(十一):友元+内部类+匿名函数

我们在实现日期类的时候有试过在Date类里重载operator<<,然后发现不行,因为在类里重载,那重载函数的第一个形参是隐含的this指针,第二个才是cout,所以它的用法是d1(Date类的对象)<<cout。注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。友元分为:友元函数和友元类。

2024-11-03 09:17:43 1083

原创 【C++】类和对象(十):static成员

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;因为n在静态区,不在对象里。静态成员不属于某个具体的对象,它属于该类的所有对象,所以在声明时不能有缺省值,存放在静态区。我们现在想知道,一共定义了多少个A类的对象,怎么办?

2024-11-01 16:00:00 452

原创 【C++】类和对象(九):再谈构造函数

我们知道,编译器生成的无参的构造函数对内置类型不做处理,对自定义类型会调用它的默认构造函数。上图中的Date类里我们写了带参的构造函数。问:会不会调用类A的默认构造函数?会不会编译错误?会调用类A的默认构造函数,不会编译错误。因为定义对象时一定要对成员变量初始化,即成员变量都要走初始化列表。所以对自定义类型的成员变量,要调用它的默认构造函数。A类中确实有默认构造函数,因此不会编译错误也就是说如果类A中没有默认构造函数,那么会编译错误。除了给类A加默认构造函数外,还有没有什么别的方法能处理这个错误。

2024-11-01 07:00:00 587

原创 【C++】类和对象(八):const成员+取地址运算符重载

构造函数和析构函数:对内置类型不做处理,调用自定义类型的构造/析构函数拷贝构造和赋值运算符重载:对内置类型值拷贝,调用自定义类型的拷贝构造/赋值运算符重载。

2024-10-31 18:00:00 470

原创 【C++】类和对象(七):运算符重载2

调试发现,在赋值完成后(编译器生成的赋值运算符重载,将对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝),st2的指向数组的指针_array和st1的指向数组的指针_array的值一样,即它们指向同一块内存空间。当然像日期类这样的类是没必要的,可在有些情况下会出错,如下面的栈(出错原因和拷贝构造函数一样)上图中,先将j赋值给i,因此i == 2,(i=j)表达式有返回值,返回的是i而非i的拷贝。运行崩溃,运行的时候出现这个错误,绝大多数都是未分配内存的原因,可以在申请空间的地方,初始化的地方多多检查。

2024-10-31 08:00:00 950

原创 【C++】类和对象(六):运算符重载1

我们这三个函数的函数名写的还不错,能明白是什么意思,那如果现在有人写了这三个函数,但是函数名分别是func1、func2、func3,我们就不能明白这三个函数分别是什么意思。从const Date到Date,权限放大,报错。因为 == 、>、<等都是双操作数的操作符,所以操作数只能有2个,this指针是“成员函数”隐含的第一个指针形参,再加上我们写的x,y一共有3个操作数,所以报错。下面的函数写在全局域里,形参用引用而非对象的传值传参,因为如果是传值传参,那就需要调用对象的拷贝构造,如果用引用就不需要。

2024-10-30 17:00:00 882

原创 【C++】类和对象(五):拷贝构造

调试发现,在拷贝完成后(编译器生成的拷贝构造函数,将对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝),st2的指向数组的指针_array和st1的指向数组的指针_array的值一样,即它们指向同一块内存空间。用已经存在的a1拷贝构造a2,此处会调用A类的拷贝构造函数,但A类并没有显式定义拷贝构造函数,则编译器会给A类生成一个默认的拷贝构造函数。如果拷贝构造函数是传值传参。

2024-10-30 07:30:00 681

原创 【C++】类和对象(四):析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。都是局部对象,后定义的先调用析构函数。

2024-10-29 17:00:00 433

原创 【C++】类和对象(三):构造函数

可是编译器生成默认的构造函数,对内置类型不做处理也不太好,于是C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即可以在类里的成员变量声明时给缺省值,这样编译器生成默认的构造函数,对成员变量里,是内置类型的就用缺省值,是自定义类型的会去调用它的默认构造函数。报错原因:对象实例化时编译器一定会自动调用构造函数,现在定义对象d1,由于Date类中存在有参的构造函数,那么编译器将不会生成无参的,d1需要无参的或者全缺省的,没有就报错。看下图,Date类没写构造函数,编译器会默认生成一个无参的构造函数。

2024-10-29 08:01:17 1093

原创 【C++】类和对象(二):this指针

C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数this,让this指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过this去访问。问:既然2个对象的Print是同一个函数,且函数体中没有关于不同对象的区分,那么为什么d1调用的Print函数知道3个变量是d1初始化的值而非d2初始化的值?this指针的类型:类的类型* const,即成员函数中,不能改变this指针的指向(指向调用该成员函数的对象)。

2024-10-28 16:00:00 809

原创 【C++】类和对象(一):初步认识

在C++中,定义类更喜欢用class。class为定义类的关键字,className为类的名字,{ }中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员,包括成员变量和成员函数成员变量和成员函数的位置:成员变量的位置可以在成员函数上,也可以在下类的两种定义方式:声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

2024-10-28 07:30:00 1669

原创 【C++】auto & for & nullptr

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,但遗憾的是一直没有人去使用它。C++11中,标准委员会赋予了auto全新的含义,即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。简单来说,就是auto能自动推导类型上图的auto类型从上到下分别是int,double,int*,int,double*,int。可以通过typeid来显示出类型如果auto只能用于上面的场景,那它相当于无用。

2024-10-12 17:00:00 1101

原创 【C++】内联函数

inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建 议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使生成的可执行文件变大,优势:少了调用开销,提高程序运行效率。因为inline被展开,就没有函数地址了,链接就会找不到。

2024-10-12 07:30:00 435

原创 【C++】函数重载+引用

在Linux中,函数名修饰以_Z为前缀,后接函数名的字符个数,再接函数名,最后是函数形参的类型缩写(按顺序)。因为func1函数运行结束后,该函数对应的栈空间就被回收了,所以变量a的空间被回收,然而函数的返回值是变量a的别名,它是野引用,因此用ret接受函数返回值时也就是访问了已被回收的a的空间,故结果是随机值。不是,a出了func1的函数作用域就被销毁,所以返回的是a的拷贝。

2024-10-08 07:00:00 798

空空如也

空空如也

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

TA关注的人

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