- 博客(31)
- 资源 (2)
- 收藏
- 关注
原创 设计模式(五)三个设计原则 单一职责、里氏替换原则、合成原则
面向对象编程中,常见的设计原则有六个:单一职责原则、开闭原则、合成原则、里氏替换原则、依赖倒转原则、接口原则、迪米特法则。这里只介绍三个,下一篇文章介绍另三个。单一职责原则这个很简单,就是一个类的职责只做一类型的事情。注意,是一类型,而不是一件事。比如上一篇文章中的EmployeeManage类,它的作用就是管理职工,所以里面可以有:初始化职工信息、查询职工、添加职工、删除职工等接口,这些接口属于同一类型,都是对员工的管理。如果员工需要换等级呢?这个接口当然也可以!那什么类型的接
2021-04-22 16:12:02
238
原创 设计模式(四)单例和简单工厂的融合
前面三篇文章介绍了三种模式:单例、简单工厂和工厂方法。其中,简单工厂和工厂方法都是基于同一个实际问题。但是,这个例子里有几个问题:1、职工的创建在main函数中,不合理,可能多个函数都会需要访问职工信息;2、职工是程序直接创建的,不合理,一旦出现新的职工入职,就需要改代码,应该改为文件方式;3、没有最基本的职工查找功能。除了以上三点,还有很多其他的待完善地方,这里先考虑这三点。代码如下(visual studio 2019):#pragma once#include <
2021-03-25 16:13:41
518
原创 设计模式(三)工厂方法模式
前一篇文章介绍了简单工厂模式,留下了一个疑问,如果需要扩展员工等级,有没有不修改既有接口的方式?答案就是工厂方法模式。既然员工的职级可以扩展,那创建对应职级员工的工厂是不是也可以扩展?工厂基类提供一个接口获取具体的产品,一旦有新的产品,就创建一个与之对象的工厂类。看代码(visual studio 2019):#pragma once#include <iostream>#include <list>//等级基类和工厂基类class GradeBase
2021-03-25 09:55:35
186
原创 设计模式(二)简单工厂
面向对象的程序中,对象的创建是一个非常重要的事情。简单工厂,就是将类的具体对象当做一个个产品,通过一个加工工厂,把这些产品创建出来,这个模式的使用频率非常大。很多公司,根据员工能力,会分为很多级别,不同级别的员工工资不一样。下面就以这个例子(这个例子会一直扩展下去),介绍一下简单工厂。很容易想到,有一个员工职级的基类,定义一个虚函数获取工资,不同职级,从这个基类派生,重写获取工资虚函数。看代码(visual studio 2019):#pragma once#include <
2021-03-25 09:23:22
114
原创 设计模式(一)单例模式
单例模式,就是对一个类来说,只有一个实例化对象(这句话不是很准确,但请不要纠结于细节,无意义)。单例有什么好处呢?因为对于整个程序来说(其实是进程),都只有一个实例,那么一些全局的变量和操作(比如链接文件关闭文件)就可以用这个唯一的对象来控制。如何让类只有一个实例对象?对于C++来说,当创建一个对象时,一定会调用类的构造函数。如果让构造函数非public呢?外部不就不能创建类的实例对象了?但是又需要有一个实例对象,怎么办呢?类成员的public等访问属性,是针对类外部的数据访问而言的(派生类对基
2021-03-23 15:32:32
341
2
原创 设计模式有用吗
说到设计模式,给人的感觉很高深莫测,而且许多有关设计模式的书,动不动加之艺术、禅等等唬人的词语,未开始学心已先怯。还有许多初学者,听前辈介绍,买了本GoF的《设计模式-可复用面向对象软件的基础》,啃了几章后,更是云里雾里不知所云,于是内心深处更是避之如蛇蝎。更有甚至,自己不会,不想学,于是乎找出各种佐证来证实设计模式对实际编程并没有什么用处,以此自欺欺人。关于设计模式,因为国内目前IT界鱼...
2021-03-18 17:07:31
767
2
原创 STL (六)map之切莫改动key
记得之前扩展一个老项目的功能,里面有一个map,key死活find不到,最后整个人都快崩溃。无奈之下,从头开始跟踪,发现前辈居然在期间强行修改了map的key,看到的那一刻,差点哭了。废话不多说,请看下面一段代码(vs2019):#include <iostream>#include <map>int main(){ using namespace std; map<int, int> mapSalary; mapSalary
2021-03-18 16:58:46
190
原创 C++基础(十九)运算符重载注意事项
类的运算符重载是C++一个非常基础也很重要的语法,很多文章都有说到,但是,很多文章里面的写法其实都是不对的,或者说不完美的。一般的运算符,可以有两种重载方式:1、作为类的成员函数;2、作为类的友元函数。作为成员函数,因为有隐藏的this指针,所以二元元素只需要一个参数即可;作为友元,二元运算符则需要两个参数。当然,有一些运算符的重载必须用友元,例如标准输入输出>>、<<等。请看下面一段代码:#include <iostream>class
2021-03-18 16:19:11
280
原创 C++基础(十八)区域设置、locale、中文乱码、中文不输出
在C++程序中,尤其是新手,在涉及到打印/输出字符串的时候,经常莫名其妙遇到乱码或者不输出的问题。如果是在windows系统上编程,更是如此。不管是CFile还是CStdioFile,莫名其妙就输出不了或者输出的是乱码。如果只是想要解决输出问题,很简单,很多文章直接让setlocale(LC_ALL, "")、setlocale(LC_CTYPE, "")、setlocale(LC_ALL, "chs")、setlocale(LC_ALL, "zh_CN")等等,反正就是setlocale,最后发现
2021-02-24 14:56:05
8789
1
原创 C++基础(十七)宽字符、wchar_t、wcout、中文乱码/不输出
上一篇文章介绍了char字符串有关的一些操作,strlen接口的实际含义,以及“一个中文占两个字节”的真实含义。char的最初设计只是为了满足英文的需求,计算机普及后各个国家和地区开始针对本地的语言进行字符编码设计,中文也是其中之一。显而易见,一个字节(char)是无法满足这些编码需求的,于是不同语言的规定一个本地字符所占字节数不定,“多字节字符集”就是这么来的。含义就是多个字节表示一个字符,一个字符可能对应一个字节,也可能对应2个甚至更多的字节。这种处理多字节很多时候对程序而言并不友好,随着硬件的
2021-02-24 14:11:06
5246
原创 C++基础(十六)字符编码 多字节字符集 字符串长度
上一篇文章介绍了sizeof的用法,它无法计算出字符串的长度,想要知道字符串的字节总数,应该怎么办呢?对于char*的字符串,用strlen函数。wchar_t,考虑到篇幅长度,另一篇文章再介绍。先看下面代码(visual stadio 2019, 64位, unicode字符集):#include <iostream>int main(){ using namespace std; const char* pStr_char_Englist = "English";
2021-02-08 16:11:28
762
1
原创 C++基础(十五)sizeof的用法 计算数组长度
sizeof本身是C语言的一个运算符,但也被C++支持,且很多C++代码中经常会出现。sizeof可以很容易计算一个数组的长度,这在数组作为参数的函数中很有用(数组作为函数参数,传入的其实是首元素的地址,必须带上数组的实际长度作为另一个参数才行)。请看下面代码(visual stadio 2019环境编译,unicode字符集,x64程序):#include <iostream>int main(){ using namespace std; int iValue =
2021-02-08 15:02:52
5529
原创 C++基础(十四)继承构造函数、委派构造函数
这是C++11里的知识,如果所用的编译器不支持,直接忽视;我用的IED:visual stadio 2019。1、继承构造函数构造函数非常重要,但有时候真是又爱又恨,尤其是在一些类的继承中,子类和基类的构造函数完全相同,却需要将所有基类的构造函数全部重新写一遍,非常厌烦。C++11推出了继承构造函数的概念,对于很多继承类,无需再重复编写完全一样的构造函数。例如,公司根据职工的能力不同分为不同等级,各个等级的基本工资和绩效工资都不一样,绩效工资与各个月的绩效系数挂钩。据此,可以设计出很简单
2021-01-18 13:38:38
244
原创 C++基础(十三)函数指针
函数指针,指向函数的指针,顾名思义,其本质还是一个指针!可以对其进行赋值(包括nullptr),当然也能判断是否为空。函数的类型,由它的返回类型和形参类型、形参个数共同决定,与函数名无关。所以函数指针,也只关心这些。1、定义定义一个函数指针,只需要指定返回值类型和形参(包括个数和类型)。在返回值和形参类型中间,加上函数指针的变量名,以及"*",并用一对小括号包起来即可。如下:返回类型 (*函数指针名)(形参)例如:double(*pf)(double)。注意两点:(1)"*pf"
2021-01-06 11:48:57
767
原创 C++基础(十二)一个宏使用的坑
虽然C++一直在强调尽量少用宏,但是宏确实是个好东西,会使代码很简洁,使人欲罢不能。近期出现一个无法理解的异常,找了很长时间,结果发现是调用的别人的宏导致的,差点吐血。实际工作中,日志是定位程序错误的常用手段之一。不同等级的日志输出,代表不同的错误级别,有一些仅仅是警告,对程序运行无任何影响,则只需要打印出来即可;但有一些是严重的错误,会对后续程序的运行影响很大,除了打印信息外,最好还能直接断言,提示开发人员。程序实际运行时,一般错误日志都是写到日志文件中;而开发环境下,直接打印到控制台更方便查
2020-12-30 14:47:40
355
原创 C++基础(十一)智能指针之unique_ptr
前一篇文章介绍了共享指针shared_ptr,这篇介绍另一种智能指针:unique_ptr。1、创建与shared_ptr不同,C++11并没有提供类似std::make_shared的标准库函数来返回一个unique_ptr,但是C++14提出了类似的库函数:std::make_unique,语法如下:std::make_unique<类型>(参数列表)依然以Person类为例:class Person{public: Person(const std::stri
2020-12-16 09:24:05
1594
原创 C++基础(十)智能指针之shared_ptr
为了一定程度解决动态内存忘记释放的问题,C++引入了智能指针的概念。并且在C++11中,将智能指针进行了优化,更加方便易用。智能指针,顾名思义,实质还是指针,不过它很智能,会自己释放内存,无需程序员手动释放。其原理就是引入计数,一旦指向某一块内存的指针数为0,则直接释放内存。常用的智能指针为共享指针shared_ptr和独占指针unique_ptr,共享指针可以多个智能指针指向同一块内存;而独占指针则在某个时刻只能有一个智能指针指向某一块内存。用智能指针,需要包含头文件:#include <
2020-12-16 09:15:56
1334
原创 C++基础(八)初窥lambda、lambda在STL中应用
lambda表达式是C++11新推出来的一个概念,非常好用,但如同C++的其他知识点一样,坑也很多。想要比较全面的介绍lambda,放到一篇博客中会比较臃肿,故决定用两篇介绍。本篇重点介绍lambda的简单应用,另一篇着重介绍lambda的坑。进入正题!lambda可以理解成局部函数,即函数中定义一个函数,与STL算法搭配使用,会极其方便。可以这么说,有了lambda,STL如虎添翼。但是!lambda也可以定义成全局的,即不再函数内定义。但这种做法有违了lambda的设计初衷,直接用普通函
2020-11-05 17:14:52
2379
原创 C++基础(九)再谈lambda 值捕获、引用捕获、隐式捕获以及避坑
lambda的基础只是及用法,已在另一篇文章中阐明,此处不再赘述。下面,介绍一些lambda表达式的另一些主要注意的点。修改值捕获的非静态局部变量前一篇文章中已说明,想要在lambda表达式的函数体中修改非静态局部变量的值,需要引用捕获。如果非要修改值捕获的变量,有方法吗?有!加上关键字mutable。但是!修改对原变量无任何影响!代码如下:int _tmain(int argc, _TCHAR* argv[]){ using namespace std; string
2020-11-05 17:13:34
31604
1
原创 STL(五)去重
想要去除容器中的重复元素,可以用STL提供的函数std::unique。与stl的其他删除函数类似,该函数并没有真正删除重复元素,只是移动了元素的位置,返回需要删除的逻辑位置。除此之外,std::unique只能去除相邻的重复元素。什么意思呢?请看下面代码:int _tmain(int argc, _TCHAR* argv[]){ using namespace std; list<int> lstInt = { 1, 2, 4, 8, 2, 2, 3, 4, 5, 8
2020-11-03 17:16:43
1242
原创 C++基础(七)初窥stringstream、istringstream、ostringstream
通过stringstream,可以将字符串对象和流进行绑定,像操作I/O流一样操作字符串。这里,介绍几个简单的应用案例:打印英文单词出现的频率:void printFrequency(const std::string& str){ using namespace std; std::map<string, int> mapFre; stringstream ss(str); string strWord; //存放单个单词 while (ss >>
2020-10-30 16:12:07
345
原创 C++基础(五)const、常量指针、常量、指向常量的指针
常量有些变量,因为程序需要,不能在编程过程中对其进行修改,则用"const"关键字修饰即可,如下:const int iTest = 100;或者 int const iTest = 100;这称为常量。一经定义后,便不能再修改。以上两种定义都是合法的!const 引用对于上面的常量,因为其数据不能修改,所以其对应的引用,也要不能修改,这样的引用,则为const 引用,如下:const int& rTest = iTest;如果定义一个普通的引用指向iTest,例如 i.
2020-10-10 11:27:35
1428
1
原创 STL(四) std::string /std::wstring 查找、删除、替换(find erase replace)
std::string(std::wstring)类,在C++中是一个非常重要同时地位也很悬殊的存在,不管程序规模大小,很难避免不用到。功能很强大,但是总感觉距离好用还差了那么一点点。首先,需要明白一点,std::string是STL中的一员,所以,有关stl的诸多算法和理念,都适用于它。有关std::string的基本操作,不过多介绍,到处都能找到,这篇博客,重点介绍平常编程经常遇到的字符串的查找、替换和删除操作。查找std::string 的查找,用std::find函数当然也没问题
2020-09-27 14:00:09
8916
原创 STL(三)删除元素 remove、erase
STL功能很强大,但是说到删除元素,不少人会觉得有些上头,这里,用vector和list两个最常用容器举例。
2020-09-23 17:35:52
6701
原创 STL(二)emplace 及指针的坑
最近在重构一个近十年前的项目,快要成了猪头。晕乎乎之际,不得不佩服前辈们的思维,如此混乱不堪的代码,居然能够跑起来,腻害腻害!改着改着,直接崩了,一脸懵逼。搜寻之下,原来是有一个巨大的类,里面有非常多的指针,但是,他又在几十个地方重复的构造和析构。效率?内存泄漏?那是操作系统的事情,根本不用考虑,复制粘贴一把梭!吐槽到此结束!分隔线-----------------------------------------------------------------------------------
2020-09-17 17:24:25
1011
原创 STL(一) 算法 for_each、transform
所有的stl算法,想要调用,都需包含头文件#include <algorithm>for_each函数原型:for_each (InputIterator beg, InputIterator end, UnaryProc op)函数功能:对区间[beg,end)中的所有元素执行 op操作。注意:op操作的返回值会被忽略。看代码: using std...
2020-04-30 09:44:21
406
原创 C++基础(四) 文件流 I/O流 文件指针 tellg tellp seekp seekg
C++中的有关文件的设计,由于历史原因,着实不太好用,里面的坑很多。一、常见文件打开方式文件模式常量含义 常量 含义 ios_base::in 以读的方式打开文件 ios_base::out 以写的方式打开文件 ios_base::ate 打开文件,并移到文件尾 ios_base::app 追加到文件尾 ios_base::trunc ...
2020-04-20 17:04:02
1671
1
原创 C++基础(三) 格式控制 setf、setiosflags等详解及避坑
C++提供的输出格式,可以简单理解成一个个标志位。我们对输出格式的控制,其实就是将相应的标志位打开、关闭和设置。内部的实现原理,不必太过深究,会用就行。但需要注意,有些标志位只需要打开或者关闭即可,比如左对齐、右对齐,但是,有些标志位则是需要具体数值或者字符,比如设置宽度和填充字符。对这些标志位的修改(打开或关闭),因为历史原因,方式有很多。究竟哪种方式好,没有定论。但是我们在写程序时,尽量使...
2020-04-16 12:48:29
5857
原创 C++基础(二)地址输出
C++用字符串存储位置的指针来表示字符串,指针的形式可以是数组、wchar_t(char)指针。但是对于其他类型的指针,C++将其对应于void*,并将其地址打印出来。所以,如果想要打印字符串的地址,将其指针强制转换成其他类型的指针即可,如下: using std::endl; using std::wcout; setlo...
2020-04-14 16:20:39
2738
原创 C++基础(一)构造函数、拷贝构造函数与赋值操作符
对于C++初学者甚至是略有编程经验的研发人员来说,构造函数、拷贝构造函数、赋值操作符(赋值构造函数)既简单有难理解,甚至经常在这上面吃亏。网络上关于这三者的介绍也很多,其中不乏经典之作;但正是由于有关文章很多,良莠不齐,许多人的解释并不贴切,甚至是错误的,这导致许多初学者越看越糊涂。 在很多文章中,将这三者放在一起讨论,甚至某些权威出版社的C++书籍也是如此,将赋值操作符叫做“赋值拷...
2018-07-02 18:10:54
247
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人