C++编程规范.docx

上传人:b****3 文档编号:10514970 上传时间:2023-05-26 格式:DOCX 页数:19 大小:26.65KB
下载 相关 举报
C++编程规范.docx_第1页
第1页 / 共19页
C++编程规范.docx_第2页
第2页 / 共19页
C++编程规范.docx_第3页
第3页 / 共19页
C++编程规范.docx_第4页
第4页 / 共19页
C++编程规范.docx_第5页
第5页 / 共19页
C++编程规范.docx_第6页
第6页 / 共19页
C++编程规范.docx_第7页
第7页 / 共19页
C++编程规范.docx_第8页
第8页 / 共19页
C++编程规范.docx_第9页
第9页 / 共19页
C++编程规范.docx_第10页
第10页 / 共19页
C++编程规范.docx_第11页
第11页 / 共19页
C++编程规范.docx_第12页
第12页 / 共19页
C++编程规范.docx_第13页
第13页 / 共19页
C++编程规范.docx_第14页
第14页 / 共19页
C++编程规范.docx_第15页
第15页 / 共19页
C++编程规范.docx_第16页
第16页 / 共19页
C++编程规范.docx_第17页
第17页 / 共19页
C++编程规范.docx_第18页
第18页 / 共19页
C++编程规范.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

C++编程规范.docx

《C++编程规范.docx》由会员分享,可在线阅读,更多相关《C++编程规范.docx(19页珍藏版)》请在冰点文库上搜索。

C++编程规范.docx

C++编程规范

C++编程规范

第0条

不要拘泥与小节

只规定需要规定的事情:

不要强制施加个人喜好或者过时的做法。

有些问题只是个人喜好,并不影响程序的正确性或者可读性,所以这些问题不应该出现在编程的规范中。

应该在每个源文件乃至每个项目中都使用一致的格式,因为同一段代码中要在几种编程风格之间换来换去是很不舒服的。

但是无需在多个项目或者整个公司范围内强制实施一致的格式。

第1条

在高警告级别干净利落地进行编译

高度重视警告:

使用编译器的最高警告级别。

应该要求构建是干净利落的(没有警告)。

理解所有的警告。

通过修改代码而不是降低警告级别来排除警告。

成功的构建应该是没有警告的,如果不是这样,你很快就会养成不仔细查看输出的习惯,从而漏过真正的问题,因为良性警告的后面可能隐藏着未来指向真正危险的警告。

第2条

使用自动构建系统

一次案按键就解决问题:

使用完全自动化(单操作)的构建系统,无限用户干预即可构建整个项目。

第4条

在代码审查上投入

审查代码:

更多的关注有助于提供质量。

亮出自己的代码,阅读别人的代码。

互相学习彼此都会受益。

好的代码审查过程对开发团队有许多方面的益处,它能够

●通过来自同伴的良性压力提高代码的质量

●找出错误、不可移植的代码和潜在的扩展问题

●通过思想交流获得更好的设计和实现

●快速培养新同事和初入门者

●在团队中形成共同的价值观和集体主义

●增加整体实力,提升自信心、动力和职业荣誉感

第5条

一个实体应该只有一个紧凑的职责

一次只解决一个问题:

只给一个实体(变量、类、函数、名称空间、模块和库)赋予一个定义良好的职责。

随着实体变大,其职责范围自然也会扩大,但职责不应该发散。

第6条

正确、简短和清晰第一

软件简单为美:

正确优于速度。

简单优于复杂。

清晰优于技巧。

安全优于不安全。

第7条

编程中应该知道何时和如何考虑可伸缩性

小心数据的爆炸性增长:

不要进行不成熟的优化,但是要密切关注渐进复杂性。

处理用户数据的算法对所处理的数据量耗费的时间应该是可预测的,最好不差于线性关系。

如果能够证明优化必要而且非常重要,尤其在数据量逐渐增长的情况下,那么应该集中精力改善算法的O(N)复杂性,而不是进行小型的优化,比如节省一个多余的家法运算。

第8条

不要进行不成熟的优化

快马无需鞭策:

不成熟优化的诱惑非常大,而它的无效性也同样严重。

优化第一原则就是:

不要优化。

优化的第二原则(仅适于于专家)是:

还是不要优化。

再三测试,而后优化。

第10条

尽量减少全局和共享数据

共享会导致冲突:

避免共享数据,尤其是全局数据。

共享数据会增加耦合度,从而降低可维护性,通常还会降低性能。

第11条

隐藏信息

不要泄密:

不要公开提供抽象的实体的内部信息。

为了尽量减少操作抽象的调用代码和抽象的实现之间的依赖性,必须隐藏实现内部的数据。

否则,调用代码就能够访问——或者更糟,操作——该信息,而原本应属于内部的信息就泄漏给了调用代码所依赖的抽象。

第12条

懂得何时和如何进行并发性编程

如果应用程序使用了多个线程或者进程,应该知道如何尽量减少共享对象,以及如何安全地共享必须共享的对象。

第13条

确保资源为对象所拥有。

使用显式的RALL和智能指针

C++的“资源获取即初始化”惯用法是正确处理资源的利器。

RALL使编译器能够提供强大且自动的保证,这在其他语言中可能需要脆弱的手工编写的惯写法才能实现的。

分配原始资源的时候,应该立即将其传递给属主对象。

永远不要在一条语句中分配一个以上的资源。

第14条

宁要编译时和连接时错误,也不要允许时错误

能够在编译时做的事情,就不要推迟到运行时:

编写代码时,应该在编译期间使用编译器检查不变式,而不应该在运行时在进行检查。

运行时检查取决于控制流和数据的具体情况,这意味很难知道检查的是否彻底。

相比而言,编译时检查与控制流和数据无关,一般情况下能够获得更高的可信度。

第15条

积极使用const

const是我们地朋友:

不变地值易于理解、跟踪和分析,所以应该尽可能地使用常量代替变量,定义值的时候,应该把const作为默认的选项:

常量很安全,在编译时会对其进行检查,而且它与C++的类型系统已浑然一体。

不要强制转换const的类型,除非要调用常量不正确的函数。

第16条

避免使用宏

宏是C和C++语言地抽象设施中最生硬的工具,它是披着函数的外衣的饥饿的狼,很难驯服,它会我行我素地游走于各地。

要避免使用宏。

第17条

避免使用“魔数”

程序设计并非魔术,所以不要故弄玄虚:

要避免在代码中使用诸如42和3014159这样地文字常量。

它们本身没有提供任何说明,并且因为增加了难于检测地重复而使维护更加复杂,可以用符号名称和表达式来替换它们。

第18条

尽可能局部地声明变量

避免作用域膨胀,对于需求如此,对于变量也是如此。

变量将引入状态,而我们应该尽可能少地处理状态,变量的生存期也是越短越好。

变量的生存期超过必需的长度时会产生以下几个缺点:

●它们会使程序更难以理解和维护

●它们的名字会污染上下文

●它们不能总是被合理地初始化

第19条

总是初始化变量

未初始化的变量是C和C++程序重错误的常见来源。

养成在使用内存之前先清除的习惯,可以避免这种错误,在定义变量的时候就将其初始化。

第20条

避免函数过长,避免嵌套过深

短胜于长,平优于深:

过长的函数和嵌套过深的代码块的出现,经常是因为没能赋予一个函数以一个紧凑的职责所致,这两种情况通常都能够通过更好的重构予以解决。

第21条

避免跨编译单元的初始化依赖

不同编译单元中的名字空间级对象决不应该在初始化上相互依赖,因为其初始化顺序是未定义的。

这样做会惹出很多麻烦,轻则在项目中稍做修改就会引发奇怪的崩溃,重则出现严重的不可移植问题。

第22条

尽量减少定义性依赖。

避免循环依赖。

不要过分依赖:

如果用前向声明能够实现,那么就不要包含(#include)定义。

循环依赖是指两个模块直接或者间接地互相依赖。

互相依赖的多个模块并不是真正的独立模块,而是紧紧胶着在一起的一个更大的模块,一个更大的发布单元。

因此,循环依赖有碍于模块性,是大型项目的祸根。

请避免循环依赖。

第23条

头文件应该自给自足

应该确保所编写的每个头文件都能够独自进行编译,为此需要包含其内容所依赖的所以头文件。

建议头文件不应该包含其他头文件,因为多次打开和分析带包含保护符的头文件会增加开销。

许多现代的C++编译器能够自动识别头文件保护符,甚至不会两次打开同一个头文件。

第24条

总是编写内部#include保护符,决不要编写外部#include保护符

为头(文件)添加保护:

在所以头文件中使用带有唯一名称地包含保护符,防止无意的多次包含。

第25条

正确地选择通过值、指针或者引用传递参数

正确选择参数:

分清输入参数、输出参数和输入/输出参数,分清值参数和引用参数。

正确地传递参数。

第26条

保持重则操作符的自然语义

只在有充分理由时才重载操作符,而且应该保持其自然语义;如果做到这一点很困难,那么你可能已经误用了操作符重载。

第27条

优先使用算术操作符和赋值操作符的标准形式

如果要定义a+b,也应该定义a+=b:

在定义二元算术操作符时,也应该提供操作符的赋值形式,并且应该尽量减少重复,提高效率。

第28条

优先使用++和――的标准形式。

优先调用前缀形式

第29条

考虑重载以避免隐含类型转换

隐式类型转换提供了语法上的便利,但如果创建临时对象的工作并不必要而且适于优化,可以提供签名与常见参数类型精确匹配的重载函数,而且不会导致转换。

第30条

避免重载&&、||或,(逗号)

内置地&&、||和,(逗号)得到编译器的特殊照顾,如果重载它们,它们就会变成普通函数,具有完全不同的语义,这肯定会引入微妙的错误和缺陷。

不要轻率地重载这些操作符。

第31条

不要编写依赖于函数参数求值顺序的代码

函数参数的求值顺序是不确定的,因此不要依赖具体的顺序。

第32条

弄清所要编写的是哪种类

有很多种不同的类,弄清楚要编写的是哪一种。

第33条

用小类代替巨类

分而治之:

小类更容易编写,更易于保证正确、测试和使用。

小类更有可能适用于各种不同的情况。

应该用这种小类体现简单的概念,不要用大杂烩的类,它们要实现的概念既多又复杂。

第34条

用组合代替继承

避免继承带来的重负:

继承是C++中第二紧密的耦合关系,仅次于友元关系,紧密的耦合是一种不良的现象,应该尽量避免。

因此,应该用组合代替继承,除非知道后者确实对设计有好处。

第35条

避免从并非要设计成基类的类中继承

在C++中,定义基类时需要做一些特定的工作,而定义独立类时则需要做另外一些大不相同甚至相反的工作。

从独立类中继承将使代码面临大量问题,而且其中很少有编译器能够发出警告或者报错。

第36条

优先提供抽象接口

抽象接口有助于我们集中精力保证抽象的正确性,不至于受到现实或者状态管理细节的干扰。

优先采用实现了抽象接口的设计层次结构。

第37条

公用继承即可替换性。

继承,不是为了重用,而是为了被重用。

公用继承能够使基类的指针或者引用实际指向某个派生类的对象,既不会被破坏代码的正确性,也不需要改变已有代码。

不要通过公用继承重用(基类中的已有)代码,公用继承是为了被(已经多态地使用了基对象的已有代码)重用的。

第38条

实施安全的改写

改写一个虚拟函数时,应该保持可替换性;说得更具体一些,就是要保持基类中函数的前后条件。

不要改变虚拟函数的默认参数。

应该显式地将改写函数重新声明为virtual。

谨防在虚拟类中隐藏重载函数。

第39条

考虑将虚拟函数声明为非公用的,将公用函数声明为非虚拟的

在基类中进行修改代价高昂:

请将公用函数设计为非虚拟的,应该将虚拟函数设为私有的,或者如果派生类需要调用基类版本,则设为保护的。

第40条

要避免提供隐式转换

并非所有的变化都是进步:

隐式转换所带来的影响经常是弊大于利。

在为自定义类型提供转换之前,请三思而行,应该依赖的是显式转换。

第41条

将数据成员设为私有地。

无行为地聚集(C语言形式的struct)除外

将数据成员设为私有的。

要避免将公用数据和非公用数据混合在一起,因为这几乎总是设计混乱的标志。

第42条

不要公开内部数据

避免返回类所管理的内部数据的句柄,这样类的客户就不会不受控制地修改对象自己拥有的状态。

第43条

明智地使用Pimpl

抑制语言的分离欲望:

C++将私有成员指定为不可访问的,但并没有指定为不可见的。

虽然这样做自有好处,但是可以考虑通过Pimpl惯用法使私有成员真正不可见,从而实现编译器防火墙,并提高信息隐藏度。

第44条

优先编写非成员非友元函数

要避免交成员费:

尽可能将函数指定为非成员非友元函数。

第45条

总是一起提供new和delete

它们是一揽子交易:

每个类专门的重载void*operatornew(parms)都必须与对应的重载voidoperatordelete(void*,parms)相随相伴,其中parms是额外参数类型的一个列表。

数组形式的new[]和delete[]也同样如此。

第46条

如果提供类专门的new,应该提供所有标准形式(普通、就地和不抛出)

如果类定义了operatornew的重载,则应该提供operatornew所有三种形式——普通(plain),就地(in-place)和不抛出(nothrow)的重载。

不然,类的用户就无法看到和使用它们。

第47条

以同样的顺序定义和初始化成员变量

与编译器一致:

成员变量初始化的顺序与类定义中声明的顺序始终保持一致;不要考虑构造函数初始化列表中编写的顺序。

要确保构造函数代码不会导致

混淆地指定不同地顺序。

第48条

在构造函数中用初始化代替赋值

设置一次,到处使用:

在构造函数中,使用初始化代替赋值来设置成员变量,能够防止发生不必要的运行时操作,而输入代码的工作量则保持不变。

第49条

避免在构造函数和析构函数中调用虚拟函数

从构造函数或者析构函数直接或者间接调用未实现的纯虚拟函数,会导致未定义的行为。

如果设计方案希望从基类构造函数或者析构函数虚拟分派到派生类,那么需要采用其他技术,比如后构造函数。

第50条

将基类析构函数设为公用且虚拟的,或者保护且非虚拟的

如果允许通过指向基类Base的指针执行删除操作,则Base的析构函数必须是公用且虚拟的。

否则,就应该是保护且非虚拟的。

第51条

析构函数、释放和交换绝对不能失败

它们的一切尝试都必须成功:

决不允许析构函数、资源释放函数或者交换函数报告错误,即就是绝对不允许将那些析构函数可能会抛出异常的类型用于C++标准库。

第52条

一致地进行复制和销毁

既要创建,也有清除。

第54条

避免切片。

在基类中考虑用克隆代替复制。

对象切片是自动地、不可见的,而且可能会使漂亮的多态设计终止。

在基类中,如果客户需要进行多态(完整的、深度的)复制的话,那么请考虑禁止复制构造函数和复制赋值操作符,而改为提供虚拟的Clone成员函数。

第55条

使用赋值的标准形式

在实现operator=时,应该使用标准形式——具有特定签名的非虚拟形式。

第57条

将类型及其非成员函数接口置于同一名字空间中

如果要将非成员函数(特别是操作符和辅助函数)设计成类X的接口的一部分,那么就必须在与X相同的名字空间中定义它们,以便正确调用。

第58条

应该将类型和函数分别置于不同的名字空间中,除非有意想让它们一起工作

要避免将类型和模板化函数或者操作符放在相同的名字空间中。

第59条

不要在头文件中或者#include之前编写名字空间using

可以而且应该在实现文件中的#include指令之后自有地使用名字空间级的using声明和指令,而且会感觉良好。

第60条

要避免在不同的模块中分配和释放内存

在一个模块中分配内存,而在另一个模块中释放它,会在两个模块之间产生微妙的远距离依赖,使程序变得脆弱。

在释放内存时,用来分配内存的模块最好仍在内存中。

第61条

不要在头文件中定义具有链接的实体

具有链接的实体,包括名字空间级的变量或函数,都需要分配内存。

在头文件中定义这样的实体将导致连接时错误或者内存的浪费。

请将所以具有链接的实体放入实现文件。

第62条

不要允许异常跨越模块边界传播

第63条

在模块的接口中使用具有良好可移植性的类型

生在(模块的)边缘,必须格外小心:

不要让类型出现在模块的外部接口中,除非能够确保所有的客户代码都能正确地理解该类型。

第64条

理智地结合静态多态性和动态多态性

静态多态性和动态多态性是相辅相成的。

理解它们的有缺点,善用它们的长处,结合两者以获得两方面的优势。

第65条

有意地进行显式自定义

在编写模板时,应该有意地、正确地提供自定义点,并且清晰地记入文档。

在使用模板时,应该了解模板想要你如何进行自定义以将其用于你的类型,并且正确地自定义。

第66条

不要特化函数模板

在扩展其他人的函数模板时,要避免尝试编写特化代码;相反,要编写函数模板的重载,将其放在重载所用的类型的名字空间中。

编写自己的函数模板时,要避免鼓励其他人直接特化函数模板本身。

第67条

不要无意地编写不通用的代码

使用最通用、最抽象的方法来实现一个功能。

第68条

广泛地使用断言记录内部假设和不变式

广泛使用assert或者等价物记录模块内部(也就是说,调用代码和被调用代码有同一个人或者小组维护)的各种假设,这些假设是必须成立的,否则就说明存在编程错误(例如:

函数的调用代码检查到函数的后条件不成立)。

第69条

建立合理的错误处理策略。

并严格遵守

应该在早期开发实际、一致、合理的错误处理策略,并予以严格遵守。

策略必须包含以下内容:

●鉴别:

哪些情况属于错误

●严重程度:

每个错误的严重性或紧急性

●检查:

哪些代码负责检查错误

●传递:

用什么机制在模块中报告和传递错误通知

●处理:

哪些代码负责处理错误

●报告:

怎样将错误记入日志,或通知用户

只在模块边界改变错误处理机制。

第70条

区别错误与非错误

违反约定就是错误:

函数是一个工作单元。

因此,失败应该视为错误,或根据其对函数的影响而定。

在函数f中,当且仅当失败违反了f的一个前条件,或者阻碍了f满足其调用代码的任何前条件、实现f自己的任何后条件或者重新建立f有责任维持的不变式时,失败才是一个错误。

第71条

设计和编写错误安全代码

在所有函数中,都应该提供最强的安全保证,而且不应该惩罚不需要这种保证的调用代码。

至少要提供基本保证。

确保出现错误时程序会处于有效状态,这是所谓基本保证。

要小心会破坏不变式的错误,它们肯定都是bug。

应该进一步保证最终状态要么是最初状态(如果有错误,则会滚操作),要么是所希望的目标状态(如果没有错误,则提交操作)。

这就是所谓的强保证。

应该进一步保证操作永远不会失败。

虽然这对于大多数函数来说是不可能的,但是对于析构函数和释放函数这样的函数来说则是必须的。

这就是所谓的不会失败保证。

第72条

优先使用异常报告错误

应该使用异常而不是错误码来报告错误。

但不能使用异常时,对于错误以及不是错误的情况,可以使用状态码(比如返回码)来报告异常。

当不可能从错误中恢复或者不需要恢复时,可以使用其他方法,比如正常终止或者非正常终止。

第73条

通过值抛出,通过引用捕获

学会正确捕获(catch):

通过值(而非指针)抛出异常,通过引用(通常是const的引用)捕获异常。

这是与异常语义配合最佳的组合。

当重新抛出异常时,应该优先使用throw;避免使用throwe;

第74条

争取地报告、处理和转换错误

什么时候说什么话;在检查出并确认是错误时报告错误。

在能够正确处理错误的最近一层处理或者转换每个错误。

只有函数检查出一个它自己无法解决而且会使函数无法继续执行的错误,就应该报告错误(比如编写throw)。

第75条

避免使用异常规范

不要在函数中编写异常规范,除非不得以而为之(因为其他无法修改的代码已经使用了异常规范)。

第76条

默认时使用vector。

否则,选择其他合适的容器。

使用“正确的容器”才是正道,如果没有充分理由,那就编写vector,如果有充分的理由使用某个特定容器类型,那就用好了,表明自己做出了正确的选择。

第77条

用vector和string代替数组

不要使用C语言风格的数组、指针运算和内存管理原语操作实现数组抽象。

使用vector或者string不仅更轻松,而且还有助于编写更安全、伸缩性更好的软件。

第78条

使用vector与非C++API交换数据

vector和string:

:

c_str是与C++API通信的通道。

但是不要将跌代器当作指针。

要获取vector:

:

iteratoriter所引用的元素地址,应该使用&*iter。

一般而言,vector的存储区总是连续的,因此访问其第一个元素的地址将返回一个指向其内容的指针。

第79条

在容器中只存储值和智能指针

在容器中存储值对象:

容器假设它们所存放的是类似值的类型,包括值类型(直接存放)、智能指针和跌代器。

容器最常见的使用情形是存储直接存放的值。

如果容器拥有所指向的对象,则应该使用引用计数的智能指针容器;否则使用原始指针的容器或者其他类似指针的值比如跌代器的容器也可以。

第81条

多用范围操作,少用单元素操作

在序列容器中添加元素时,应该多用范围操作(例如接受一对跌代器为参数的insert形式),而不要连续调用该操作的单元素形式。

给一个函数提供的背景信息越多,它能用此信息完成有用任务的可能性就越大。

特别是,在调用一个函数并传给它一对限定范围的跌代器first和last时,它就可以根据所要添加的对象数量进行优化。

第82条

使用公认的惯用法真正地压缩容量,真正地删除元素

要真正地压缩容器地多余容量,应该使用“swap魔术”惯用法。

要真正地删除容器中地元素,应该使用erase-remove惯用法。

第83条

使用带检查的STL(算法)实现

即使只在其中的一个编译器平台上使用,即使只能在发行前的测试中使用,也仍然要使用带检查的STL(算法)实现。

第84条

用算法调用代替手工编写的循环

对非简单的循环而言,手工编写的循环有可能是最简单也是最有效率的解决方案,但是编写算法调用代替手工编写的循环,可以使表达力更强、维护性更好、更不易出错,而且同样高效。

第85条

使用正确的STL查找算法

选择查找方式应“恰到好处”——正确的查找方式应该使用STL;本条款适用于在一个范围内查找某个特定值,或者查找某个值的位置。

查找无序范围,应使用find/find_if或者count/count_if。

查找有序范围,应使用lower_bound、upper_bound、equal_range或者(少数情况下)binary_search(尽管binary_search有一个通行的名字。

但是选择它通常并不一定正确)。

第86条

使用正确的STL排序算法

理解每个排序算法的作用,选择能够实现所需而开销最低的算法。

并不总是需要进行完全排序的,一般情况下都不需要那么完全,而在极少数情况下才需要对更多元素进行排序。

按开销从低到高的大致顺序,应该如下选择标准排序算法:

partition、stable_partition、nth_element、partial_sort、sort和stable_sort。

应该使用能够完成实际所需功能的开销最低的算法,使用更强的算法将是一种浪费。

第88条

算法和比较器的参数应多用函数对象少用函数

对象的适配行比函数好:

应该向算法传递函数对象,而非函数。

关联容器的比较器必须是函数对象,函数对象的适配性好,而且语直觉相反,它们产生的代码一般比函数要快。

第89条

正确编写函数对象

将函数对象设计为复制成本很低的值类型。

一般函数对象应该通过值来传递。

所有标准算法都是通过值来传递对象的,我们自己的算法也应如此。

第90条

避免使用类型分支,多使用多态

避免通过对象类型分支来定制行为。

使用模板和虚函数,让类型自己来决定行为。

通过类型分支来制定行为既不牢固、容易出错,又不安全,而且是企图用C++编写C代码的明显标志。

这是一种很不灵活的技术,要添加新特性时必须回过头对现有代码进行修改。

它还不安全,因为添加新类型时,如果忘记修改所有分支,编译器也不会告知。

第91条

依赖类型,而非其表示方式

不要对对象在内存中的准确表示方式做任何假设。

相反,应该让类型决定如何在内存中读写其对象。

第93条

避免对指针使用static_cast

不要对动态对象的指针使用static_cast:

安全的替代方法有很多,包括使用dynamic_cast重构,乃至重新设计。

第94条

避免强制转换const

强制转换const有时会导致未定义的行为,即使合法,也是不良编程风格的主要表现。

选择const之后,就(应该)永不回头。

如果对象的最初定义为const,强制转换调它的常量性,将使所有保护失效,程序完全处于未定义行为状态。

第95调

不要使用C风格的强制转换

C语言风格的强制转换根据上下文具有不同(而且经常很危险)的语义,而所有这些都隐藏在相同的语法背后。

用C++风格的强制转换代替C风格的强制转换有助于防范意想不到的错误。

第97条

不要使用联合重新解释表示方式

通过在union中写入一个成员而读取另一个的滥用方式可以获得“无需

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2