当前位置:  开发笔记 > 编程语言 > 正文

与C语言相比,C++的局限性是什么?

如何解决《与C语言相比,C++的局限性是什么?》经验,为你挑选了18个好方法。

以下是C++的好处

C++提供了他们所询问的特定功能

他们的C编译器几乎肯定是一个C++编译器,所以没有软件成本的影响

C++和C一样可移植

C++代码可以和C一样有效(或者更多,或者更少)

是否有任何具体原因和特定场景,其中必须使用C over C++?

参考这个问题:C中的泛型库

这不是重复,因为这个问题是关于语言限制而不是关于应该/不应该学习一种语言而不是另一种语言.

Peter Kirkham的帖子对我来说是最有用的,特别是关于我没有考虑的C99问题,所以我接受了它.感谢参与其他所有人.



1> Pete Kirkham..:

这是由我给当前问题的答案提示的,该问题询问C的泛型库 - 提问者特别声明他们不想使用C++.

C是一种完整的编程语言.C不是C++的任意子集.C根本不是C++的子集.

这是有效的C:

foo_t* foo = malloc ( sizeof(foo_t) );

要使其编译为C++,您必须编写:

foo_t* foo = static_cast( malloc ( sizeof(foo_t) ) );

这不再是有效的C. (你可以使用C风格的强制转换,它可以在C中编译,但是大多数C++编码标准都会避开,许多C程序员也会避开;见证Stack overflow上的"不要抛出malloc"注释) .


它们不是同一种语言,如果你在C中有一个现有的项目,你不想用另一种语言重写它只是为了使用一个库.您更愿意使用可以使用您正在使用的语言进行交互的库.(在某些情况下,可以使用一些extern "C"包装函数,具体取决于C++库的模板/内联方式.)

以第一个C文件中的一个项目,我的工作,这是如果你只是交换会发生什么gcc std=c99g++:

sandiego:$ g++ -g  -O1 -pedantic -mfpmath=sse -DUSE_SSE2 -DUSE_XMM3  -I src/core -L /usr/lib -DARCH=elf64 -D_BSD_SOURCE -DPOSIX -D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112L -Wall -Wextra -Wwrite-strings -Wredundant-decls -Werror -Isrc  src/core/kin_object.c -c -o obj/kin_object.o | wc -l
In file included from src/core/kin_object.c:22:
src/core/kin_object.h:791:28: error: anonymous variadic macros were introduced in C99
In file included from src/core/kin_object.c:26:
src/core/kin_log.h:42:42: error: anonymous variadic macros were introduced in C99
src/core/kin_log.h:94:29: error: anonymous variadic macros were introduced in C99
...
cc1plus: warnings being treated as errors
src/core/kin_object.c:101: error: ISO C++ does not support the ‘z’ printf length modifier
..
src/core/kin_object.c:160: error: invalid conversion from ‘void*’ to ‘kin_object_t*’
..
src/core/kin_object.c:227: error: unused parameter ‘restrict’
..
src/core/kin_object.c:271: error: ISO C++ does not support the ‘z’ printf length modifier
src/core/kin_object.c:271: error: ISO C++ does not support the ‘z’ printf length modifier

共有69行错误,其中4行是无效转换,但主要是针对C99中存在但未存在于C++中的功能.

这并不像我正在使用这些功能来获得它的乐趣.将它移植到另一种语言需要大量的工作.

所以建议这样做是完全错误的

[a] C编译器几乎可以肯定是一个C++编译器,所以没有软件成本的影响

将现有C代码移植到C++的过程子集中通常会产生很大的成本影响.

所以建议'使用C++ std :: queue class'作为问题的答案,在C中查找队列的库实现,而不是建议'使用目标C''使用JNI调用Java java.util.Queue类'或者"调用CPython库" - Objective C实际上是C(包括C99)的正确超集,Java和CPython库都可以直接从C调用,而不必将不相关的代码移植到C++语言.

当然,您可以为C++库提供C外观,但是一旦您这样做,C++与Java或Python没有什么不同.


说C不是C++的一个子集是非常迂腐的.当然,您可以说任何带有名为"class"的成员的结构都不会编译,但实际上只需要进行少量修改,并且大多数编译器都可以选择将少数C-only功能添加到C++中.
就malloc示例而言,添加一个演员不仅会被C++程序员所避开,而且(特别是)C程序员也会避开.有充分的理由在C代码中省略演员阵容.这没有必要,添加它可能会隐藏错误.所以,是的,将它们视为两种截然不同的语言.+1 :)
@BlueRaja想象一下,如果Guido决定不在他的脚本语言中添加对象,并且两个组创建了互不兼容的Python来添加对象,一个是基于Smalltalk的对象模型,另一个是基于Simula的类系统.然后Guido继续改进Python,专注于其核心用途.这更接近于C/Objective C/C++的情况.
是.使用malloc时,C风格的强制转换很常见.当使用malloc时,它会保留在c子集中.如果要编写C++样式,可以使用operator new,而不是static_cast + malloc.
@BlueRaja:他们是两种不同的语言,共享一个相当大的共同核心.如果你在这个共同核心中编程,那么你最终会做出两种语言都不是很好的代码.选择一种语言来编写任何给定的程序,并使其适合该语言.
@KazDragon不,这不是非常迂腐.我喜欢并经常使用C的一些功能,这使我的C代码无法使用C++编译器进行编译.C不是C++的子集,它从来就不是.断言这一事实​​并非"非常迂腐".也许你不知道C或C++或者两者都知道有**巨大的**差异,但无论如何,都有.
@NoSenseEtAl我举一个用C++编译器编译一些C99代码的结果的例子.你不能将所有有效的C结构编译为C++,ergo C不是C++的子集(使用当前的C++ 0x标准,但我不确定文字对象初始化器是否会以兼容的形式进入C++).我更喜欢经验证明而不是对权威的诉求.
如果使用`-std = c99`编译它,Objective-C是C99的正确超集
@KazDragon你能想出一种方法来编译一个C源文件,该文件调用方法并使用C++中的对象吗?我知道通过(ab)使用Objective-C运行库你不仅可以使用ObjC对象和调用方法,甚至可以声明新类等.此外,一些(所有)Objective-C语言结构只是语法糖果,可以用C`#define`替换,例如`@class NSString`只是`typedef struct objc_object NSString`
@NoSenseEtAl这同样适用于您的评论.你在"Bjarne认为C是C++的一个子集"中是非常错误的.Stroustrup从未这么说过.他感到遗憾的是他"从一开始就争论强大的兼容性".他失败了.C和C++确实共享一个共同的子集(一些被误导的人喜欢称之为"纯C"),但绝对不是C是C++子集的情况.

2> dagw..:

我意识到这既不是专业也不是特别好的答案,但对我而言,这只是因为我真的很喜欢C. C小而简单,我可以将整个语言融入我的大脑,C++对我来说似乎总是一个巨大的庞大混乱各种各样的层次我很难走动.由于这个原因,我发现每当我编写C++时,我最终会花费更多的时间来调试和敲击硬表面,而不是在编写C时.我再次意识到很多这很大程度上是由于我自己的"无知".

如果我选择,我将编写所有高级的东西,如python中的接口和数据库交互(或可能是C#)以及所有必须在C中快速的东西.对我来说,它给了我最好的世界.用C++编写所有东西感觉就像是最糟糕的世界.

编辑: 我想补充一点,我认为如果你要成为一个项目的几个人或者可维护性是优先考虑的话,那么带有一些C++特性的C在很大程度上是一个坏主意.关于什么构成'少数'以及哪些比特应该在C中完成以及哪些比特在C++中最终导致一个非常精神分裂的代码库,将会有分歧.


我使用C++已经有好几年了,仍然花了50%的时间将代码重构为"C++正确".正如你所说,这是一场噩梦.
我使用C++已经十年了,回到C(对于我的情况下的嵌入式系统)是我做过的最好的事情.
你可以随时第一次做到这一点.添加const并不困难.
+1,_由于这一点,我发现每当我编写C++时,我最终会花费更多的时间来调试和敲击硬表面,而不是编写C_时.不能同意你的意见.最好的答案.:)

3> Joonas Pulak..:

在某些真实环境中,例如低级嵌入式系统,不支持C++.并且有一个很好的理由:对于这样的事情,C很容易就足够了,为什么要使用更大的东西呢?


@BlueRaja:与模板相比......多重继承可能不是真正的威慑.在所有模板构成了他们自己的完全成熟的语言之后.
当然.如今不是所有的8位芯片都有C编译器.
对.我见过8位微控制器的c编译器.

4> Georg Schöll..:

我讨厌用C++编程.


非常有说服力!我正在考虑根据你的论点切换到Python.
也许没有说服力,但这才是真正的原因.
大声笑我喜欢那个
@Georg:我承认我从来没有看过,我对Python印象深刻.

5> jalf..:

可能有以下几个原因:

缺乏支持 - 并非每个C编译器都是C++编译器.并非所有编译器都特别符合标准,即使他们声称支持C++.而一些C++编译器会产生无望的膨胀和低效的代码.一些编译器具有标准库的可怕实现.内核模式开发通常不可能使用C++标准库,以及一些语言功能.如果你坚持使用该语言的核心,你仍然可以编写C++代码,但是切换到C可能更简单.

熟悉.C++是一门复杂的语言.教C之人比C++更容易,而且找一个优秀的C程序员比一个优秀的C++程序员更容易.(这里的关键字是"好的".有很多C++程序员,但大多数都没有正确学习语言)

学习曲线 - 如上所述,教授某人C++是一项艰巨的任务.如果你正在编写一个将来必须由其他人维护的应用程序,而这些其他人可能不是C++程序员,那么用C语言编写它会让你更容易掌握.

我仍然更喜欢用C++编写,当我可以逃脱它时,总的来说,我认为好处大于缺点.但我也可以看到在某些情况下使用C的论点.


我想补充说C代码的编译速度比C++快得多.我们公司的一个庞大项目(超过一百万行)的编制时间不到30秒.

6> Anders Hanss..:

有很多关于嵌入式编程,性能和东西的争论,我不买.在这些领域,C++很容易与C进行比较.然而:

就在最近用C++编程超过15年后,我一直在重新发现我的C根.我必须说,虽然C++中有很好的功能可以让生活更轻松,但也有很多陷阱和一种"总是更好的方式".你从未真正对你所做的解决方案感到高兴.(不要误解我的意思,这可能是一件好事,但大多数情况下并非如此).

C++为您提供无限的枪声.这可能是好的,但不知怎的,你总是最终使用太多.这意味着您通过"漂亮"和"漂亮"的抽象层次,一般性等来伪装您的解决方案.

我发现回到C的原因是它实际上又是有趣的编程.花了这么多时间建模并思考如何最好地使用继承,我发现用C编程实际上使我的源代码更小,更易读.这当然取决于你的自律水平.但是在直接代码上放置过多的抽象是非常容易的,这实际上并不需要.


再一次,我不认为C++是一种OO语言,它不应该被视为一种语言.我认为泛型编程是C++的一个更强大的特性.我看到的大多数C++代码并没有特别难以成为"OO",或者包含不必要的代码.它通常比等效的C代码更精简
没有冒犯,但它也可能取决于你认为C++是什么.继承是我与Java相关的东西而不是C++,如果你把C++严格地当作Java的OOP语言(带有类的C),那么我同意你的看法.如果你坚持使用更现代的C++,我认为它比C更有趣
@jalf:我发现的另一件事就是在C++中成为一种"总有一种更好的方式"分心,就是用模板来概括."也许我们应该让这个类的用户决定使用什么底层整数类型?" 但你可能不需要*那个,而在C中你不会打扰.有时我发现自己在想,"我们应该为这个类提供一个前向迭代器接口,"在C语言中,你只需要暴露一个指向第一个元素和一个计数的指针,或者(一个幻想的高度!)一个函数回调函数指针.
我发现在C++编码帮助时退一步.决定目标,并写下它(C风格).因为它们的用处变得明显,所以C++主义因素也是如此.
"无限的枪声",是的,是的,如此真实.我们的脚真的颤抖:)

7> x4u..:

C的主要优点是,当你查看一些代码时,你可以看到真正发生的事情(是的预处理器:用-E编译,然后你看到它).当你看一些C++代码时,往往不常见的事情.在那里你有构造函数和析构函数,它们基于作用域或由于赋值而被隐式调用,你有操作符重载,即使它没有被严重误用,也会产生令人惊讶的行为.我承认我是一个控制狂,但我得出结论,对于想要编写可靠软件的软件开发人员来说,这不是一个坏习惯.我只是想有一个公平的机会说我的软件完全按照它应该做的那样,同时我的胃里没有一种不好的感觉,因为我知道它仍然会有很多错误,我不会

C++也有模板.我讨厌并爱他们,但如果有人说他或她完全理解他们,我称他/她为骗子!这包括编译器编写者以及参与定义标准的人(当你尝试阅读它时会变得很明显).有很多荒谬的误导性案例涉及到在编写实际代码时根本无法全部考虑它们.我喜欢C++模板,因为它们具有强大的功能.你可以用它们做什么真的很神奇,但它们同样可以导致最奇怪和最难找到错误的人可以(不)想象.而这些错误实际上发生了,甚至很少发生.阅读有关解决C++ ARM模板所涉及的规则几乎让我头疼.并且它让我感觉浪费时间不得不读取长度为1000个字符的编译器错误消息,我需要10分钟或更长时间才能理解编译器实际需要的内容.在典型的C++(库)代码中,您还经常在头文件中找到大量代码以使某些模板成为可能,这反过来使得即使在快速机器上编译/执行周期也很慢,并且当您更改某些内容时需要重新编译大部分代码那里.

C++也有const陷阱.除了最琐碎的用例之外,您可以避免使用const,或者您迟早要将其丢弃或者在它发展时重构代码库的大部分内容,尤其是当您即将开发一个漂亮而灵活的OO设计时.

C++具有比C更强的类型,这很好,但有时我觉得我在尝试编译C++代码时正在喂一个Tamagotchi.我通常从中得到的警告和错误的很大一部分并不是我做了一些不起作用的事情,而是编译器不喜欢我这样做的事情,如果没有在这里投出或添加一些额外的关键字,那里.

这些只是我不喜欢C++软件的一些原因,我只使用一些据称强大的外部库来单独编写软件.当你与其他人一起编写代码时,真正的恐怖就开始了.它们是非常聪明的C++黑客还是天真的初学者并不重要.每个人都会犯错误,但是C++会故意找到它们,甚至在它们发生之前更难发现它们.

使用C++,你总是在不使用调试器的情况下丢失,但我希望能够在头脑中验证代码的正确性,而不必依赖调试器来查找我在前所未有的路径上运行的代码.我实际上尝试在我的头脑中运行我的所有代码并尝试获取它拥有的所有分支,甚至在子程序等中.并且偶尔使用调试器只是为了看看它在我为它准备的所有舒适的地方运行得如何.编写和执行如此多的测试用例,使得所有代码路径都被用于所有类型的奇怪输入数据的组合是根本不可能的.所以你可能不知道C++程序中的错误,但这并不意味着它们不存在.C++项目越大越低,我相信它不会有很多未被发现的错误,即使它与我们手边的所有测试数据完美匹配.最终我把它丢弃并重新开始使用其他语言或其他语言的组合.

我可以继续,但我想我现在已经说清楚了.当我用C++编程并且让我对自己的代码的正确性失去信心,这意味着我将不再使用它,而我仍然使用并依赖于我编写的20多个C代码时,所有这些都让我觉得没有效果几年前.也许这只是因为我不是一个优秀的C++程序员,或者在C语言方面表现相当不错,而其他语言让我能够认识到在C++方面我实际上是什么样的,而且我永远无法完全理解它.

生命短暂...


+1,不能同意.
这听起来与Linus的观点非常平行.(较少的对象上下文=更容易理解.)

8> bstpierre..:

在低级嵌入式环境中,一些"软件工程师"将拥有EE背景并且几乎没有掌握C. C++更复杂,其中一些人只是害怕学习一门新语言.因此,C被用作最小公分母.(在你建议摆脱这些家伙之前,他们至少和那些不了解核心模拟东西的CS专业人士一样重要.)

从继承和维护两者的经验谈起:C中的可怕设计很难理解,放松和重构成可用的东西.

随机抽象层将你的大脑放在代码库周围,试图找出哪些代码将在哪种情况下执行,因此C++中的可怕设计无限糟糕.

如果我必须与我知道不会产生出色设计的工程师合作,我宁愿拥有前者而不是后者.



9> Suma..:

即使对嵌入式系统和类似的东西进行编程,我也没有看到任何个人不喜欢的理由.在C++中,您仅为您使用的功能支付开销.在C++开销过高的某些特定情况下,您可以使用C++的C子集.这就是说,我认为一些C程序员高估了一些C++结构的开销.让我列举一些例子:

与普通函数相比,类和成员函数的开销为零(除非使用虚函数,在这种情况下与使用函数指针相比​​没有开销)

模板的开销很小(通常根本没有开销)

一个合理的原因是当你为一个没有合适的C++编译器的平台编程时(根本没有C++编译器,或者编译器存在,但实现很差,并且对某些C++特性施加了不必要的高开销).


比什么更开销?该类型在vtbl中携带.如果使用函数指针实现类似的机制,则至少需要一个指针(或索引或​​其他)来选择要使用的函数指针.
有一个开销,但我的意思是,如果你想要任何动态类型解析,你需要一些存储来识别类型,即使在C中.如果你不想要动态类型,你不需要支付开销(如果你不需要虚拟函数,请不要使用它们.
具有虚函数的类具有更多开销:每个实例必须携带额外的字段来标识类型.
bstpierre:我认为Suma所说的是:它没有比在C中自己手动实现该功能更多的开销.
指向类vtable的指针存储在类的每个实例中.
这个虚函数是一个完整的侧面.Suma的帖子声称"你只为你使用的功能支付开销".如果您不使用虚拟功能,则不需要支付开销.如果您不能忍受开销,请不要使用它们.

10> SPWorley..:

为什么限制英语口语?也许你会成为塞尔维亚人更具创造力的作家.

这是相同的论点,有明显的谬误.如果您有任务,并且您的舒适工具可以有效地解决任务,那么您可能会使用舒适的工具.


如果我说流利的英语和流利的塞尔维亚语,我相信我会更有创意.你不同意吗?
@Neil确实如此,但学习塞尔维亚语所需的努力可能不足以解决我目前的创造力.
我认为Arno强调的事实是你不是在为CPU写作,而是为同事写作,以及你要链接的其他库,等等.毕竟,如果我只是为了表达和速度,我会写在OCaml.

11> quinmars..:

C++有更长的学习曲线.C只有很少的构造需要注意,然后你就可以开始编写功能强大的软件了.在C++中,你需要学习C基础,然后是OO和泛型编程,异常等.经过一段时间你可能知道大多数功能,你可能会使用它们,但你仍然不知道编译器将如何翻译他们,他们有或没有隐含的开销.这需要很多时间和精力.

对于一个专业项目,这个论点可能不算数,因为你可以雇用已经熟悉C++的人.但是在开源项目中,C仍然使用了widley,人们会选择他们喜欢的语言并且能够使用.考虑到并非每个OS程序员都是专业程序员.


在C++中没有自动内存管理这样的东西.
C可能"较小"但从长远来看它不容易使用.手动内存管理?不用了,谢谢.
C++没有解决内存管理问题.就在你认为自己掌握指针的时候,C++会添加一个非常糟糕的异常模型.来到C99的土地,除了数据结构,我很确定我几乎没有碰到malloc.即使这样,我也可以"封装"一些malloc调用.这与C++中的故事大致相同(隐式内存管理,只在堆上而不是堆栈上完成),只有所有的智能指针爵士乐.

12> TrayMan..:

我想跟进Dan Olson的回答.我相信人们担心C++的潜在危险和适得其反的特性,并且理所当然.但与丹所说的不同,我不认为简单地决定编码标准是有效的,原因有两个:

    编码标准可能难以严格执行

    想出一个好的很难.

我认为这里的第二个原因比第一个原因重要得多,因为决定编码标准很容易成为一个政治问题,并在以后进行修订.考虑以下简化案例:

    您可以使用stl容器,但不能在任何自己的代码中使用模板.

    人们开始抱怨如果他们只是被允许编写这个或那个模板类,他们会更有效率.

    修改编码标准以允许这样做.

    将斜率滑动到一个过于复杂的编码标准,没有人遵循,并使用标准本应防止的那种危险代码,并结合标准周围的过多官僚作风.

(标准在步骤3中没有修改的替代方案在经验上太不可能考虑,反正也不会那么好.)

虽然几年前我曾经使用过几乎所有的C++,但我开始强烈地认为C在需要由C或C++处理的低级任务中是首选,而其他一切都应该在其他一些任务中完成.语言完全.(只有可能的例外是一些特定的高性能问题域,wrt.Blitz ++)



13> Rhythmic Fis..:

我使用C,或者在编写库代码时至少导出一个C接口.

我不想要不明确的ABI麻烦.



14> Dan Olson..:

我从来没有见过任何关于使用C over C++的论据,我认为这些论点令人信服.我认为大多数人都害怕C++提供的某些功能,通常是合理的.然而,这并不能说服我,因为人们可以通过编码标准来强制执行是否使用某些功能.即使在C中,也有很多你想要避免的东西.完全抛弃C++本质上是说它没有提供超过C的实际好处,这有助于编写更好的代码,这是我认为非常无知的观点.

此外,人们似乎总是提出没有C++编译器的平台的情况.当然C在这里是合适的,但我认为你现在很难找到像这样的平台.


我相信C++给我带来了非常小的好处,并且给我带来了大量的意外复杂性.我相信需要大约1500页的C++教科书和十年的努力才能在C++,Pascal,Python和Objective-C方面精通C++.在我使用它们的环境中,上述每种语言的正交性,紧凑性和使用方便性都要高出约20倍,更不用说功能更强大了.在我通常的开发环境中,对于C++没有合理的合理用法.
同意,"C比C++更好"的咆哮永远不会受到审查.
不是这样.如果您是项目中唯一的开发人员,那可能就是这样.但是,只要我们有两个开发人员,我们就会进行战斗.什么?你坚持使用IoC容器,而我更喜欢其他一些代理方式...你喜欢三层嵌套模板,我更喜欢零模板.一团糟.

15> Ken..:

有一点,我还没有看到,我认为这是最重要的:

我每天使用的大多数库都是带有Python,Ruby,Perl,Java等绑定的C库.从我所看到的,用19种不同的语言绑定来包装C库要容易得多.包装C++库.

例如,我曾经学过一次开罗,并且已经使用过3到4种不同的语言.大赢!我宁愿编写一个可以在将来再次使用的程序,编写一个可以很容易被其他编程语言采用的程序就是这种情况的极端情况.

我知道绑定C++库是可能的,但AFAICT并不相同.我已经在其他语言中使用过Qt(v3和v4)并且使用起来并不是很好:他们感觉就像用其他语言编写C++,而不是像本机库一样.(你必须将C++方法sigs作为字符串传递!)

如果您正在编写一次使用的函数,或者如果您认为全世界都是C++,那么C++可能是一种更好的语言.如果你从一开始就设计语言可移植性,C似乎是一种更容易的语言.



16> LegendLength..:

Windows内核开发不支持c ++(遗憾的是).


因为许多C++特性需要运行时支持,这在内核模式下实现起来可能并不简单.首先,使用不同的内存分配函数,因此必须替换标准库的块.例外通常也很糟糕.
我要补充说,Linux Torvalds幸运地在Linux中扼杀了C++的任何机会,原因多于例外.在其他语言中有一些操作系统:Java,C++,汇编程序.只有汇编者才能合理使用.

17> Paul Dixon..:

你可以阅读一个有趣的咆哮,讲述为什么Linus Torvalds 在这里赞成C.


Torvalds先生有很多他不喜欢的东西,C++,emacs,Subversion,OO等等.人们有时会希望他再多按一下嘴唇
莱纳斯喜欢咆哮并试图激怒和骚扰人们.不幸的是,在宣称它很糟糕之前,他并没有费心去学习*C++.不幸的是,他的追随者相信他所说的一切都必须是真的.
这个链接更多的是娱乐而不是教育
与针对C++的咆哮相比,它更多地是针对面向对象设计的半连贯的咆哮.
证明甚至天才有时也可以是玩偶.
你必须了解Linus所居住的空间.没有完成内核编程的任何人都不理解所涉及的约束.
无法与开始发帖的人争论"*你*充满了胡说八道." :)

18> Nick Van Bru..:

mac上的本机代码是objective-c.PC上的本机代码是c(window.h)或c ++(mfc).这两种环境都允许您在很少或没有更改的情况下使用c.当我想要一个代码库来跨平台时,似乎是个不错的选择.

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有