【问题标题】:What can be done in c but not c++? [closed]什么可以用c而不是c ++来完成? [关闭]
【发布时间】:2011-04-22 05:35:51
【问题描述】:

哪些功能可以在 C 中完成,但不能在 C++ 中完成,您在使用 C++ 编码时最怀念哪些功能?

我能想到的几件事:

  1. 我们可以将任何类型的指针分配给 void 指针,而无需在 c 中进行强制转换,但在 c++ 中则不行。
  2. 声明变量名是 C++ 中的关键字,但不是 C ;)

编辑:感谢@sbi 指出:
1.应该是:我们可以将void指针分配给C中的任何类型的指针,但在C++中则不行

【问题讨论】:

  • 问同样问题的另一种方式是“C++ 与 C 有何不兼容”,您会找到很多详尽的现有答案。
  • 这里有一个:每天编译一个项目不止一次。
  • @Als:C++ 编译 非常 很慢,一个稍微大一点的项目可能需要 小时 编译,特别是如果它使用很多模板,STL和升压。其实很多地方都用专用的编译集群,很可笑。 C 的编译速度也很慢,但与 C++ 相比还是有些合理的。
  • @imgx64:我的 100k 行项目在 4 分钟内从零开始编译。您是否在 ZX Spectrum 上编译 C++ 代码?
  • @img64:牛肚。我认为大型大型项目没有显着差异。

标签: c++ c


【解决方案1】:

注意:我想我会因此而发火,但是,对于 C++ 开发人员来说,这是一个 C++ 问题,所以...

哪些功能可以在 C 中完成,但不能在 C++ 中完成,您在使用 C++ 编码时最怀念哪些功能?

作为一名 C++ 开发人员,无论是 C99 还是其他语言,我都不会错过任何 C 语言。

我写这篇文章并不是出于恶意。 这是为错过一些 C/C99 功能的 C++ 开发人员提出的问题,因为他们忽略了 C++ 的基本功能。我确实相信这个问题及其答案忽略了 C++ 中可行或更好的替代方案(不,“C++ 向量很讨厌”的评论只是一个虚假的理由)。

这就是为什么我将在这里讨论每一个所谓的“缺失功能”......

变长数组?

可变长度数组是 C99 的语言特性。它的主要优点是:

  1. 堆栈分配
  2. 创建时可变长度
  3. 无需解除分配

对于最常见的情况,std::vector 将完成这项工作,并且无论如何都有更多功能。例如,除非我错了,否则变长数组有以下缺点:

  1. 堆栈上的分配意味着您不能从声明它的函数返回 VLA
  2. VLA 无法调整大小,这意味着如果它太小,那你就完蛋了
  3. VLA 必须在原型范围或块范围内声明。它不能是外部的或静态的。而且您不能将其声明为结构的成员。
  4. 它不能有初始化器

向量可以调整大小,并且可以返回。并且使用 C++0x(和 r 值引用),您可以使用移动语义返回一个向量,这意味着不需要无用的临时对象。你可以把它放在一个结构/类中,它可以是外部的,也可以是静态的。您可以使用默认值、数组的内容、容器或使用 C++0x 使用初始化列表来初始化它。

即使在那之后,如果你真的想要像 VLA 这样的东西,在 C++ 中,一个普通的 C++ 开发人员可以编写一个基于堆栈的类似向量的容器。 而且它不需要完整的语言委员会更新。

只是为了好玩,我碰巧发了一个answer with a simple proof-of-concept of a C++ VLA-like class。

C++ 的向量在大多数情况下是更好的选择,具有更多功能。在极少数情况下确实需要 VLA,它的功能可以通过用户定义的类来模拟。

将void * 转换为T *?

至于将任何void * 转换为另一个类型指针,这不是 C++ 中缺少的 C 特性:这是弱类型与强类型的选择

在 C++ 中也不是不可能做到这一点,而你可以通过强制转换来做到这一点。这种差异的关键在于降低 void * 不如其他语言有用的语言中的错误风险:在我当前的 C++ 100k 行项目中,void * 的出现次数为零。

指定的初始化器?

构造函数提供了更好的选择。

当然,你不可能直接初始化结构中的数据,但是,数据封装意味着大多数时候,我的对象中的数据是私有的,所以,使用指定的整个概念初始化它们的初始化器将是荒谬的。

对于类似 POD 的结构,构造函数很容易编写,并且可以处理指定的初始化程序永远不会做的情况(例如默认使用非零值初始化成员,甚至调用函数)。

由于 C++ 专注于数据封装,构造函数为指定初始化程序提供了更好的替代方案。

2011-11-05 编辑:

重读本节后,我想澄清一点:指定初始化器可能对非常有限的情况(即 POD)有用,这意味着虽然我不会错过它们(如所问在问题中),我不介意拥有它们。

复合字面量?

此句法糖再次假设您知道该结构的确切实现,并对其成员具有公共访问权限,而这在 C++ 中通常是您希望避免的。

再次重申,复合字面量不是函数、方法甚至构造函数无法处理的东西,具有额外功能的优势,如上所述。

声明变量名是 C++ 中的关键字,而不是 C 中的关键字?

我知道你的感受:每次我有可能在 C++ 中使用 interface、final 或 synchronized 时,我都会感到 Java 不寒而栗……

:-P

类型通用宏?

C 中的问题是你有很多函数,对不同的类型做相同的语义事情,这意味着每个函数必须有不同的名称。例如,根据 OpenGroup,确实存在以下功能:

  • double sin(double x);
  • float sinf(float x);
  • long double sinl(long double x);
  • 等

来源:http://www.opengroup.org/onlinepubs/009695399/functions/sin.html

但是他们的名字很难记住,所以有人想到了。关于宏,它会使用编译器内置扩展来根据所使用参数的类型调用正确的宏。

这就是 C99 的<tgmath.h> 的全部魅力。

这个想法似乎很awesome,他们甚至添加了一个提议,为下一个 C 标准中的所有函数提供此功能,例如:

#define sin(x) __tgmath(x,,,     \
float, sinf, long double, sinl,  \
/* etc. */                       \
, , sin)(x)

来源:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1340.htm

现在,令人震惊的消息是:这个功能在 C++ 中已有几十年了:这被称为函数重载。

例如,上面的函数在 C++ 中声明为:

  • double sin (double x );
  • float sin (float x );
  • long double sin (long double x );
  • 等

因此,“类型通用宏”是一种被破解的实现,它努力(部分)模拟更通用的 C++ 函数重载。

猜猜看:您甚至可以为自己的用户定义类型添加自己的重载。

结论

如上所示,每次我研究 C99 特性时,得出的结论都是:“嘿,我已经可以在 C++ 中做到了!” (通常在句子的某处加上“更好”这个词)。

说真的,作为一名 C++ 开发人员,我现在想念的是能够在工作中使用 C++0x。例如,以下 C++0x 特性:

  • auto
  • constexpr
  • 初始化列表
  • 右值参考
  • lambdas
  • nullptr
  • 等

整个“C++ 中缺少 C 的特性”是一个被高估的概念,我怀疑 C 开发人员(和 C 类开发人员)比 C++ 开发人员更感兴趣。

【讨论】:

  • +1 我自己不是 C++ 的忠实粉丝,但我有一些同情。 C99 所具有的 C++ 所没有的任何特性都不能被视为您真正想念 的东西。所以你不能隐式转换为 void 指针?哦,不,最好取消项目……或者输入七个额外的字符(void*)(或者现在 C++ 程序员所做的任何转换)。
  • @Jeremy:在 C++ 中禁止隐式转换用于转换 from void*,not to。
  • @sbi:这一点仍然存在,不是吗。这不像是禁止显式转换。
  • @Jeremy:只是你是这个帖子中第二个说将 to void* 强制转换为 C++ 的人。那是错的。 from void* 是受限制的 - 并且有充分的理由。
  • +1。说得好。但是,您不允许将自己的重载放在 std 命名空间中。但是,您可以提供您自己的某些模板的特化(例如 std::swap)。
【解决方案2】:

您可能会发现网页 Incompatibilities Between ISO C and ISO C++ 很有趣。

我主要怀念一些 C99 中没有的 C++ 特性:

  • 复合文字;
  • 指定的初始化器;
  • 可变参数宏(包含在 C++0X 中)。

【讨论】:

  • @Als:什么?这是私人网站上的一篇冗长的 C++ 文章,作者是知道自己在说什么的人,大概 much 适合喜欢 Facebook 之类的人。仅致谢列表中就有一半是 C++ 社区中的知名人士。天啊。获得一份新工作。你目前的工作阻碍了你的工作。
  • @Als:经过审查的网络连接确实限制了开发人员。我和@sbi 一起讨论这个问题。我希望他们付给你足够的钱来弥补。
  • 别忘了限制,VLA,输入泛型宏(tgmath.h)
  • @Nyan:是的,但问题是关于我错过的功能。我几乎加了restrict,但我个人不会错过VLA和<tgmath.h>。
  • @Als/@Matt/@sbi:我必须通过谷歌缓存读取我的一半页面:-/。
【解决方案3】:

不是在 C 中的一个特性,但可以说是 C 的一个杀手级特性是C89 的简单语法使得编写编译器变得容易。好吧,无论如何,与 C++ 编译器相比。

【讨论】:

  • 使用 C++,你可以用几乎完全相同的方式编写编译器,如果你愿意的话。
  • @Kaz Dragon:不,他的意思是写一个 C 编译器比用任何语言写一个 C++ 编译器都容易,因为 C 的语法要简单得多。
  • 我同意,尽管有趣的是,大多数 C++ 笨拙的语法都源于 C++ 旨在向后兼容的事实 :-)
  • @JeremyP - 哦,对了。我不是这样读的。我读到用 C 编写编译器更容易。nm
  • 我认为该语言的简单性不仅仅有益于编译器的编写者。
【解决方案4】:
  1. 我们可以将任何类型的指针分配给 void 指针,而无需在 c 中进行强制转换,但在 c++ 中则不行。

任何指针都可以在 C++ 中转换为 void*。您以这种方式丢失信息,编译器不会阻止您这样做。问题恰恰相反,因为这样您获得编译器无法检查的信息。

我认为 C 允许这样做,而 C++ 绝对不允许。

【讨论】:

  • 我想知道为什么这被否决了。它有什么问题?
【解决方案5】:

如果我们忽略明显的差异来源 - C99 - 将自己限制在 C89/90 中,同时丢弃琐碎的变体,如 C++ 关键字,C 和 C++ 之间仍然会有一些差异

(1) 您已经提到了将void * 转换为任何具体指针类型而无需强制转换的能力。

(2) 带有“未指定”参数的函数类型,即函数类型声明中的()。在 C 中你可以这样做

void foo(int, int);
void bar(double);

int main() {
  void (*pf)();

  pf = foo;
  pf(1, 2); /* valid call */

  pf = bar;
  pf(5.0);  /* valid call */
}

这在 C++ 中是不可能的。当然,也可以说通用的非原型函数声明是 C 的一个特性,而 C++ 中没有(同样适用于 C99)。

(3) 数组初始化与字符串字面量的一些区别:后面的\0在C中允许脱落,但在C++中不允许脱落

char str[2] = "ab"; /* valid C, not valid C++ */

(4) C 中的暂定定义,尽管它们大多无关紧要。

(5) 另一个几乎无关紧要的“功能”:在 C 中,您可以使用“忘记”实际返回任何内容的值返回函数

int foo() {
}

代码在 C 和 C++ 中都是合法的,但在 C++ 中这样的函数会无条件地产生未定义的行为。在 C 中,只有当您实际尝试使用返回值时,该函数才会产生未定义的行为

foo(); /* fine in C, undefined behavior in C++ */

(6) 如果我记得的话,我会在以后添加一些其他内容。

【讨论】:

  • 你真的想念那些功能吗?
  • @paercebal:小姐?这些天我主要在 C 中工作,所以我不会“想念”它们。无论如何,在 OP 的上下文中,是否有人错过了这些功能是无关紧要的。
  • 我的错。有两个问题:问题是“哪些事情可以用 C 而不是 C++,在 C++ 中编码时你miss 最喜欢这些功能中的哪些?”......我想我专注于miss 部分,阅读“可以在 C 中完成但不能在 C++ 中完成的事情,而您在使用 C++ 进行编码时会错过这些事情”...
  • @paercebal:好的。好吧,通常我根本不会在我的 C 代码中使用任何这些功能(除了void * 转换),所以如果我使用 C++ 工作,我可能不会错过任何一个。
  • void * 转换在我的 C 中也被大量使用
【解决方案6】:

您可以在 C 中使用 variable-length array,但在 C++ 中则不行。我相信这将非常有用,而不是为此执行new[]。

【讨论】:

  • 但是 C++ 有std::vector<>。
  • vector 在堆上分配内存,VLA 可能在栈上分配内存。由于大多数时候堆分配比堆栈分配更昂贵,我相信这会很有用。
  • @Matt:那是让您希望对评论投反对票的 cmets 之一。你毫无根据地指责它。我该怎么办,但不理会它?
  • @Matt:我不确定矢量是如何强迫你的。如果您不需要调整大小,std::array 适合您。另外,我不知道std::vector 在哪些方面将非 POD 与 POD 区别对待(除了某些实现可能会根据区别进行优化)。我已经教了 C++ 多年,我可以证明初学者似乎发现 std::vector 比 C 数组更容易理解。最后,我还没有看到显示 std::vector 比 C 数组慢的测量结果。
  • @Matt Joiner:“向量是数组的有限实现:”不。向量是可以模仿数组的对象,并具有附加功能。至于性能问题,我上次分析代码时,strlen 是有罪的一方,而不是 C++ 向量或字符串。
【解决方案7】:

在语法糖和类型滥用方面存在一些细微差别,但它们很容易解决。

C 最重要的能力是生成完全独立的程序,绝对没有外部依赖。这就是为什么操作系统内核几乎普遍用 C 编写的原因。C 实际上是为实现操作系统而设计的。可以在 C++ 的受限子集中编写 OS 内核,但如果有的话,仅在链接时执行这些限制,因此处理这些问题比处理细微的语法差异要痛苦得多。

【讨论】:

    【解决方案8】:

    在 C 中,您可以在 void 指针和其他指针之间进行隐式转换,但您必须在 C++ 中进行显式转换。

    void* void_ptr;
    int* int_ptr;
    
    int_ptr = void_ptr;  // Invalid in C++, but not in C
    void_ptr = int_ptr;  // Valid in C and C++
    void_ptr = (void*)int_ptr; // Valid in C and C++
    int_ptr = (int*)void_ptr;  // Valid in C and C++
    

    【讨论】:

    • 是吗?我必须仔细检查。
    • 而且 b = a 在 C++ 中是非法的。
    【解决方案9】:

    我在 C 中喜欢的是能够说查看类似 a = b; 的内容并确切地知道它在做什么。在 C++ 中,任何人都可以覆盖运算符,这意味着像这样的简单语句最终可能会调用一些庞大的复制构造函数(或者更糟糕的是,完全不相关的东西)。您在 C++ 中看到 a = b;,您必须猜测(或去查找)是否有人这样做只是为了烦人。

    【讨论】:

    • 这是一个“世界上到处都是破坏者!”综合征。您既不信任您的同事(或您的图书馆提供者),也不信任语言本身。如果您与会做与语义上下文无关的事情的人一起工作(例如重载+ 并在内部编码-)并且会“只是为了烦人”而这样做,那么您应该寻找另一份工作。和普通人一起用 C++ 编写代码很有启发性:在 10 多年的职业生涯中,我从来没有和你描述的白痴一起工作过,当一些代码效率低下时,大多数时候,它不是在运算符重载代码中。跨度>
    • ... 现在,a = b 示例是一个很好的示例。在 C++ 中,这意味着a 将成为b 的副本。如果b 是一个大对象,那么您可以打赌副本会很昂贵。这里重要的部分是“如果b 是一个大对象”。如果我们忽略“破坏者”的阴谋论,这意味着在 C++ 中,类型很重要,而在 C 中,重要性在于函数。这就是我写“相信语言”的原因。要在 C++ 中正常工作,您需要从“过程”切换到“对象应该表现”的观点。如果没有这个开关,那么你看到的只是恶意代码。
    • 我的问题更多是因为我无法查看低效的代码并看到它是低效的,因为 C++ 和 OOP 共同提供了抽象。 (我不希望破坏,但我确实希望很多时候它们会使 CPU 跳过比满足我的特定需求所绝对必要的更多的箍。)同时,我不能只相信抽象, 因为在某些情况下 (std::endl?) 它会导致更多的浪费。 C++ 有一个奇怪的中间地带,你必须关心一些细节而不是其他细节,而在 C 中,陷阱在哪里更清楚。
    • @cHao:您的“我无法查看低效代码并发现它是低效的”模式仅适用于 C 运算符。对于其他一切,它是无用的。而在 C 语言中,这意味着大多数代码,因为运算符,根据定义,几乎什么都不做。结论是,和其他人一样,如果您需要衡量某些代码的性能,则需要对其进行概要分析(或查看源代码,然后猜测)。
    • @paercebal:在 C++ 中,它可能意味着所有代码。 C 运算符“几乎什么都不做”这一事实可能是一件好事。当您没有伪装成操作员的功能时,这意味着更少需要担心的事情。不要误会我的意思;我倾向于喜欢运算符重载可以提供的表现力。但与此同时,它扼杀了“运营商几乎什么都不做”的规则。这条规则是我喜欢 C 的原因之一:a + b 或 a = b 或 a(b) 就是它的样子,并不是一个巨大的操作,并且不会根据它的操作改变它的含义开。
    【解决方案10】:

    作为 C 的粉丝,我认为编码风格的概念中可能还有另一点,那就是函数式编程,与称为 OOP 的面向对象编程形成对比!对于那些将代码编写为状态机的人来说,这是一个非常有趣的概念!考虑 opengl 作为一个很好的例子。由于内存引用较少,在 C 中运行代码的速度也非常好。您可能还喜欢听到许多程序员喜欢用 C 编写代码,因为设计简单且习惯了 C 语言(语法上可能不那么容易)。哦,当你想编写非常接近硬件级别的代码时,你应该使用纯 C。

    【讨论】:

    • 事实:C++ 对硬件的访问与 C.__ 相同。事实:人们可以在 C++ 中使用多种编码风格。包括 C 风格的编码。__ 事实:当代码由一个体面的编码人员编写时,C 和 C++ 代码将具有相同的速度。__ 事实:C++ 与 OOP 无关。 C++ 是关于多种工具的,包括 OOP、模板元编程、过程式编程、函数式编程。这意味着 C++ 代码能够为任务选择最佳样式。有时它是类似 C 的代码。更常见的是,这是范式的混合。这里的关键词是choice。
    • 事实:“C 风格”C++ 受到 C++ 纯粹主义者的不满(阅读:语言势利小人)。请注意“没有称为 C/C++ 的语言”cmets,其中问题都被标记了。说“你可以用 C++ 编写 C 风格的代码”是不诚实的,因为这样做的人很可能会因此受到批评。
    • @cHao:有时,您必须在 C++ 代码中编写 sprintf。如果 sprintf 被正确封装,并且被编写以避免其不安全的陷阱,这仍然是 C++ 代码。 “C 风格”的 C++ 更多是关于过程式编程,使用 C 标准库,并且不被反对(除非它是不小心做的)。现在,避免构造函数并改用 memset,使用指向函数的指针而不是函数或 C++ 信号,用函数和结构污染全局命名空间,以及用 char * 而不是 std::string 乱扔代码是正确的不赞成...
    • @cHao: ... 有一些 C 模式应该小心编写,因为它们会导致错误(没有明确所有者的指针、void * 和强制转换、指向函数的指针、未初始化的结构等。 ),而且恰好 C++ 拥有将这些模式编写在一个安全行中的所有工具。 C++ 开发人员选择忽略 C++ 方式而支持不太安全的 C 方式只是自找麻烦。这是不受欢迎的。
    【解决方案11】:

    C99 缺少的一个特性是 VLA,C++ 应该没有与之对应的特性。

    有些人甚至质疑用 C++ 编写类似 VLA 的对象的可能性。

    这就是我添加这个答案的原因:尽管有点离题,但它仍然表明,使用正确的库,C++ 开发人员仍然可以访问模仿 C99 特性的对象。因此,这些功能并没有像人们想象的那样被遗漏。

    主要代码是:

    #include <iostream>
    #include <string>
    #include "MyVLA.hpp"
    
    template <typename T>
    void outputVLA(const std::string & p_name, const MyVLA<T> & p_vla)
    {
        std::cout << p_name << "\n   MyVla.size() : ["
                  << p_vla.size() << "]\n" ;
    
        for(size_t i = 0, iMax = p_vla.size(); i < iMax; ++i)
        {
            std::cout << "   [" << i << "] : [" << p_vla[i] << "]\n" ;
        }
    }
    
    int main()
    {
        {
            MY_VLA(vlaInt, 5, int) ;
    
            outputVLA("vlaInt: Before", vlaInt) ;
    
            vlaInt[0] = 42 ;
            vlaInt[1] = 23 ;
            vlaInt[2] = 199 ;
            vlaInt[3] = vlaInt[1] ;
            vlaInt[4] = 789 ;
    
            outputVLA("vlaInt: After", vlaInt) ;
        }
    
        {
            MY_VLA(vlaString, 4, std::string) ;
    
            outputVLA("vlaString: Before", vlaString) ;
    
            vlaString[0] = "Hello World" ;
            vlaString[1] = "Wazaabee" ;
            vlaString[2] = vlaString[1] ;
            vlaString[3] = "Guess Who ?" ;
    
            outputVLA("vlaString: After", vlaString) ;
        }
    }
    

    如您所见,MyVLA 对象知道它的大小(这比在 C99 VLA 上使用 sizeof 运算符要好得多)。

    当然,MyVLA 类的行为类似于一个数组,并由 size_t 值(可以在运行时更改)进行初始化。唯一的故障是由于函数alloca() 的性质造成的,这意味着只能通过宏 MY_VLA 间接使用构造函数:

    下面是类的代码,在文件 MyVLA.hpp 中

    #include <alloca.h>
    
    template <typename T>
    class MyVLA
    {
        public :
            MyVLA(T * p_pointer, size_t p_size) ;
            ~MyVLA() ;
    
            size_t          size()                          const ;
            const T &       operator[] (size_t p_index)     const ;
            T &             operator[] (size_t p_index) ;
    
        private :
            T * m_begin ;
            T * m_end ;
    } ;
    
    #define MY_VLA(m_name, m_size, m_type)                                                      \
    m_type * m_name_private_pointer = static_cast<m_type *>(alloca(m_size * sizeof(m_type))) ;  \
    MyVLA<m_type> m_name(m_name_private_pointer, m_size)
    
    template <typename T>
    inline MyVLA<T>::MyVLA(T * p_pointer, size_t p_size)
    {
        m_begin = p_pointer ;
        m_end = m_begin + p_size ;
    
        for(T * p = m_begin; p < m_end; ++p)
        {
            new(p) T() ;
        }
    }
    
    template <typename T>
    inline MyVLA<T>::~MyVLA()
    {
        for(T * p = m_begin; p < m_end; ++p)
        {
            p->~T() ;
        }
    }
    
    template <typename T>
    inline size_t MyVLA<T>::size() const
    {
        return (m_end - m_begin) ;
    }
    
    template <typename T>
    inline const T & MyVLA<T>::operator[] (size_t p_index) const
    {
        return *(m_begin + p_index) ;
    }
    
    template <typename T>
    inline T & MyVLA<T>::operator[] (size_t p_index)
    {
        return *(m_begin + p_index) ;
    }
    

    宏是一团糟,可能写得更好。类本身可能不是异常安全的,但可以做到。无论如何,它需要更多代码才能使用(即处理复制/分配,使新/删除私有,尽可能添加const,等等)。我的猜测是,结局并不能证明我花在上面的时间是合理的。所以它仍然是一个概念验证。

    关键是“C++ 可以模拟 C99 VLA,它甚至可以作为 C++ 对象数组工作!”,我想我成功地证明了这一点。

    我让读者复制粘贴编译代码来查看结果(我在 g++ 4.4.3 上编译,在 Ubuntu 10.04 上编译。

    【讨论】:

      【解决方案12】:

      在 C 中,您可以定义要删除的变量名称。你不能在 C++ 中做到这一点。

      【讨论】:

        【解决方案13】:

        C 和 C++ 的主要区别在于 C++ 是面向对象的,而 C 是面向函数或过程的。面向对象的编程范式专注于编写更具可读性和可维护性的程序。它还通过打包一组相似的对象或使用组件编程模型的概念来帮助代码的重用。它通过使用对象、继承和多态的现实世界概念来帮助以逻辑方式思考。应该注意的是,这些功能也有一些缺点。例如,在程序中使用多态会降低该程序的性能。

        另一方面,函数式和过程式编程主要关注动作和事件,而编程模型关注触发程序代码执行的逻辑断言。

        【讨论】:

        • 您可以编写面向对象的 C 代码(我们在工作中这样做),面向对象是一种设计原则,而不是该语言的特性。对于开源替代方案,我相信 OpenSSL 是合理的面向对象的。
        • 我觉得这有点回收了。 C++ 的(少数)优点之一是它不会强迫您使用 OO。
        • @Matt Joiner:C 也不强迫你写 OO 代码。
        • @Martin York:我并没有提出其他建议......即使这个答案也没有提出建议。相关性?
        • @Christoffer:当编译器支持时,OO 会更好。如果不是这样,您最终会手工完成许多编译器做得更好的事情。如果你不是你的语言的超级大师,那么代码的使用和调试将会很痛苦(更不用说学习曲线了)。最好中的最好:如果您正在为 C++ 编译器编写 OO C 代码,那么您一定错过了一些东西。就我而言,我见过一个“面向对象的 C 在 C++ 编译器上工作”的案例,但结果远非漂亮。
        猜你喜欢
        • 2012-10-22
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 1970-01-01
        • 1970-01-01
        • 2019-08-03
        • 2013-09-19
        • 1970-01-01
        相关资源
        最近更新 更多