有什么可以在C,但不是C做++? [英] What can be done in c but not c++?

查看:102
本文介绍了有什么可以在C,但不是C做++?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是可以在C,但不是在C ++中做的事情,以及这些功能你最怀念的,而用C ++编码?

几件事我能想到的:


  1. 我们可以将任何类型的指针指向void没有投在C,但不是在C ++中。

  2. 声明的变量名在C ++的关键字,但不是C;)

编辑:您指出由于@sbi:​​结果
1.应该是:我们可以空指针分配给任何类型的C指针,但不是在C ++


解决方案

注:我想我会得到火烧了这一点,但是,那么,它是C ++ developpers一个C ++的问题,所以...


  

什么是可以在C,但不是在C ++中做的事情,以及这些功能你最怀念的,而用C ++编码?


作为一个C ++开发者,我想没有从C,无论是C99或以其他方式。

我不写这篇文章是为了泄愤。 这是C ++开发谁错过了一些C / C99功能,因为他们忽略了C ++ 的基本特征的问题。我相信,问题和答案,忽视用C或可行更好的替代品++(不,在C ++载体是讨厌的评论只是一个虚假的理由)。

这就是为什么我会在这里讨论的所谓的功能缺失......

每一个

变长数组?

变长数组是C99的语言功能。它的主要优点是:


  1. 在堆栈
  2. 分配
  3. 在创建可变长度

  4. 没有必要释放

对于最常见的情况下,的std ::矢量将做的工作,并有更多的功能呢。例如,除非我错了,变长数组有以下缺点:


  1. 在栈上分配意味着你不能从函数返回一个VLA它被宣布

  2. 的VLA不能调整大小,这意味着如果它太小,那么你就完蛋了

  3. VLA必须无论是在原型范围中声明,或阻止范围。它不能的extern,或静态的。而你不能声明为结构的成员。

  4. 它不能有一个初始化

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

甚至在这之后,如果你真正想要的东西,如VLA,在C ++中,它有可能为平均C ++开发人员编写基于堆栈的矢量般的容器。 和它不会需要一个完整的语言委员会更新。

只是为了好玩,我正好张贴<一个href=\"http://stackoverflow.com/questions/3879636/what-can-be-done-in-c-but-not-c/3901262#3901262\">answer用一个简单的验证的概念C ++ VLA-状类的。

C ++的载体是大部分时间一个更好的选择,具有更多的功能。而在极少数情况下是真的真的需要一个VLA,其功能可以由用户定义的类效仿。

铸造无效* T *

至于铸造任何无效* 成另一种类型的指针,这是不是从C ++缺少一个C的特点:这是弱类型的VS选择。强类型

和它的不作为,如果这是不可能做到这一点在C ++中,你可以用铸铁做。这个不同点是一门语言,以减少错误的风险,其中无效* 并不像在其他有用:在我目前的C ++ 10万线项目,我有零发生无效*的

指定的初始值?

构造提供了一个更好的选择。

当然,你没有得到在结构中直接初始化数据的可能性,但随后,数据封装意味着大部分的时间,我对象的数据是私有的,所以,使用指定的整个概念初始化初始化它们将是荒谬的。

至于POD状结构,以及,一个构造函数很容易编写,并能处理案件指定的初始值永远不会做(如默认初始化非零值的成员,甚至调用函数)。

由于C ++的重点放在数据封装,构造提供给指定的初始化一个更好的选择。


  

修改2011-11-05:


  
  

重新阅读本节之后,我想澄清一点:指定的初始的非常有限的情况下(即吊舱),这意味着虽然我不想念他们有用(如问在这个问题),我不会介意这些。


复合文字?

本语法糖假设,再次,你知道这两个结构的具体实施,并给其成员的公开访问,这是你平时要避免东西C ++。

再次,复合文字是不是可以不通过一个功能,方法或者甚至构造进行处理,具有附加功能的优点,如上述

声明的变量名在C ++的关键字,但不是C?

我知道你的感受:每次我都用的可能性接口最后同步在C ++中,我得到的的Java 的颤抖,太...

- P

类型泛型宏?

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


  • 双重罪(双X);

  • 浮动SINF(浮X);

  • 长双sinl(长双X);



  

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


不过,他们的名字是一个真正的痛苦记忆,所以有人出了个主意。一些有关它将使用内置的扩展一个编译器根据类型中使用的参数来调用正确的宏

这是C99的&LT的所有魔法; tgmath.h方式&gt;

和想法显得那么,他们甚至还添加了一个命题来提供此功能为所有真棒在接下来的C标准功能,具有类似:

 的#define SIN(X)__tgmath(X ,,, \\
浮动,SINF,长双,sinl,\\
/ *等* / \\
,罪过)(X)


  

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


现在,令人震惊的消息:该特性是​​数十年以来在C ++中提供:这就是所谓的函数重载

例如,上面用C ++声明的功能:


  • 双重罪(双X);

  • 浮动罪(浮X);

  • 长双罪(长双X);


所以,类型泛型宏观调控是被攻击的实现,努力(部分)模拟比较通用的C ++函数重载。

和猜测什么。你甚至可以添加自己的重载自己的用户定义类型

结论

如上图所示,每次我研究了C99的功能,得出的结论是:嘿,我已经可以做,在C ++! (通常用好的地方在句子)。

严重的是,作为一个C ++开发者,我怀念的现在是要能使用的C ++ 0x的工作。例如,下面的C ++ 0x的特点:


  • 汽车

  • constexpr

  • 初始化列表

  • r值引用

  • lambda表达式

  • nullptr


整个从C C缺少的功能++是一个被高估的概念,我怀疑,是更有趣的C语言开发人员(和C-带类的开发人员),比C ++开发人员。

What are the things that can be done in C but not in C++, and which of these features do you miss the most while coding in C++?

Few things I can think of:

  1. We can assign any type of pointer to void pointer without cast in c but not in c++.
  2. Declare variable names that are keywords in C++ but not C ;)

EDIT : Thanks @sbi for pointing out:
1. should be: We can assign void pointer to any type of pointer in C but not in C++

解决方案

Note: I guess I'll get flamed for this, but, then, it is a C++ question for C++ developpers, so...

What are the things that can be done in C but not in C++, and which of these features do you miss the most while coding in C++?

As a C++ developer, I miss nothing from C, be it C99 or otherwise.

I do not write this just out of spite. This is a question for C++ developers who miss some C/C99 features because they ignore basic features of C++. I do believe the question and its answers ignore viable or better alternatives in C++ (and no, the "C++ vector are nasty" comment is just a bogus reason).

This is why I will discuss here each one of the supposed "missing features"...

Variable-length arrays?

Variable length arrays is a language feature of C99. Its key advantages are:

  1. allocation on stack
  2. variable length on creation
  3. no need to deallocate

For the most common cases, std::vector will do the job, and have more features anyway. For example, unless I'm wrong, the variable-length array have the following disadvantages:

  1. allocation on the stack means you can't return a VLA from the function where it was declared
  2. the VLA can't be resized, meaning that if it's too small, then you're screwed
  3. VLA must be either declared at prototype scope, or block scope. It can't be extern, or static. And you can't declare it as a member of a struct.
  4. It cannot have an initializer

The vector can be resized, and can be returned. And with C++0x (and the r-value references), you can return a vector using move semantics, meaning no useless temporary object is needed. You can put it in a struct/class, it can be extern, or static. you can initialize it with a default value, the content of an array, a container, or, with C++0x, with an initializer list.

And even after that, if you really want something like the VLA, in C++, it is possible for an average C++ developer to write a stack-based vector-like container. And it would not need a full language committee update for that.

Just for the fun, I happened to post an answer with a simple proof-of-concept of a C++ VLA-like class.

C++'s vector is most of the time a better alternative, with more features. And in the rare case a VLA is really really needed, its features could be emulated by a user-defined class.

Casting void * into T *?

As for casting any void * into another typed pointer, this is not a feature of C missing from C++: This is a choice of weak-typing vs. strong-typing

And it's not as if it was impossible to do it in C++, as you can do it with a cast. The point of this difference is to decrease a bug risk in a language where void *is not as useful as in another: In my current C++ 100k lines project, I have zero occurrences of void *.

Designated initializers?

Constructors offers a better alternative.

Of course, you don't get the possibility of initializing directly the data in the struct, but then, data encapsulation means that most of the time, the data in my objects are private, so, the whole concept of using designated initializers to initialize them would be ridiculous.

As for POD-like structures, well, a constructor is easy to write, and can handle cases designated initializers won't ever do (like initializing members with non-zero values by default, or even calling functions).

Because C++'s focus on data encapsulation, constructors offer a better alternative to designated initializers.

Edit 2011-11-05:

After re-reading this section, I want to clarify one point: Designated initializers can be useful for very limited cases (i.e. PODs), meaning that while I don't miss them (as asked in the question), I wouldn't mind having them.

Compound Literals?

This syntactic sugar supposes, again, that you know both the exact implementation of the struct, and have a public access to its members, which is something you usually want to avoid in C++.

Once again, Compound Literals are not something that can't be handled by a function, method or even constructor, with the advantage of bonus features, as described above.

Declare variable names that are keywords in C++ but not C?

I know how you feel: Each time I have the possibility of using interface, final or synchronized in C++, I get Java shivers, too...

:-P

Type-generic macro?

The problem in C is that you have quite a bunch of functions, doing the same semantic thing to different types, meaning the each function must have a different name. For example, according to the OpenGroup, the following functions do exist:

  • double sin(double x);
  • float sinf(float x);
  • long double sinl(long double x);
  • etc.

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

But their names are a real pain to remember, so someone had an idea. Something about a macro which would use a compiler built-in extension to call the right one according to the types of the used parameters.

This is all the magic of C99's <tgmath.h>.

And the idea seemed so awesome that they even added a proposition to offer this feature for all functions in the next C standard, with something like:

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

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

Now, the shocking news: This features is available in C++ since decades: This is called function overloading.

For example, the functions above are declared in C++ as:

  • double sin (double x );
  • float sin (float x );
  • long double sin (long double x );
  • etc.

So, the "Type-generic macro" is a hacked implementation, which strives to (partially) emulate the more generic C++ function overloading.

And guess what: You can even add your own overloads for your own user-defined types.

Conclusion

As shown above, each time I study a C99 feature, the conclusion is: "Hey, I already could do that in C++!" (and usually with the word "better" somewhere in the sentence).

Seriously, as a C++ developer, what I miss right now is to be able to use C++0x at work. For example, the following C++0x features:

  • auto
  • constexpr
  • initialized lists
  • r-value references
  • lambdas
  • nullptr
  • etc.

The whole "C missing features from C++" is an overrated concept which, I suspect, is more interesting to C developers (and C-with-classes developers) than C++ developers.

这篇关于有什么可以在C,但不是C做++?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆