←back to thread

In Defense of C++

(dayvster.com)
185 points todsacerdoti | 1 comments | | HN request time: 0.209s | source
Show context
butterisgood ◴[] No.45268696[source]
A pet peeve of mine is when people claim C++ is a superset of C. It really isn't. There's a lot of little nuanced differences that can bite you.

Ignore the fact that having more keywords in C++ precludes the legality of some C code being C++. (`int class;`)

void * implicit casting in C just works, but in C++ it must be an explicit cast (which is kind of funny considering all the confusing implicit behavior in C++).

C++20 does have C11's designated initialization now, which helps in some cases, but that was a pain for a long time.

enums and conversion between integers is very strict in C++.

`char * message = "Hello"` is valid C but not C++ (since you cannot mutate the pointed to string, it must be `const` in C++)

C99 introduced variadic macros that didn't become standard C++ until 2011.

C doesn't allow for empty structs. You can do it in C++, but sizeof(EmptyStruct) is 1. And if C lets you get away with it in some compilers, I'll bet it's 0.

Anyway, all of these things and likely more can ruin your party if you think you're going to compile C code with a C++ compiler.

Also don't forget if you want code to be C callable in C++ you have to use `extern "C"` wrappers.

replies(6): >>45269029 #>>45270860 #>>45273486 #>>45277585 #>>45279380 #>>45280485 #
lelanthran ◴[] No.45279380[source]
> void * implicit casting in C just works, but in C++ it must be an explicit cast

In C, casting a `void *` is a code smell, I feel.

Most confusing one is how the meaning of `const` differs between C and C++; I'm pretty certain the C `const` keyword is broken compared to `const` in C++.

replies(1): >>45344238 #
1. 1718627440 ◴[] No.45344238[source]
Yes, casting in general is a code smell. (Not as in never use it, but as in use it as less as possible of course.)

The thing is, void was introduced exactly to represent this use-case without casting. The type to represent random amount of bytes, check which type and then cast is called char *. void * is for when you know exactly which type it has you just need to pass it through a generic interface, which isn't supposed to know or touch the type. The other use case is for when the object hasn't a type yet, like from malloc.

Previously everything was typed char *, then void * was used to separate the cases: casting from char *, don't cast from void *. Now in C++ both are the same again.