References are kind of redundant when you already have pointers, and they make the performance characteristic of the code you read less clear (am I passing down a pointer, or am I copying the whole thing?).
C structs can already do most of what C++ classes can do. Including inheritance and virtual methods, when you really really need them. As for encapsulation, pointer to implementation provide a more stable, harder to cheat interface than private members. A must for stable ABIs.
C does lack generics, and I do often miss them, but templates really aren't a good solution. I don't know what a good solution looks like, I haven't looked at Zig or Rust yet.
Another thing I miss in C is a namespace system, especially when you ship libraries: makes every name longer, and you still have annoying name clashes from time to time.
> References are kind of redundant when you already have pointers,
No. They're not. References must point to valid objects (i.e., cannot be nullptr and cannot be random addresses in memory), and you cannot do arithmetic on them. They are much safer to use than pointers, so actually, references make pointers redundant.
> C structs can already do most of what C++ classes can do. Including inheritance and virtual methods, when you really really need them.
Yes, references have nice constraints that makes them harder to misuse than pointers. The gap however is smaller than it first look: dangling references are still a thing, and one does not simply make pointer arithmetic by accident. Don't get me wrong, I do like references enough that my C++ code is littered with them. I'm just saying they don't add that much to the table. They're nice, but I never really miss them when I write C.
Yes, writing your own virtual table in C is mighty cumbersome. On the other hand, I need those about once every 3 years, even in C++.
C structs can already do most of what C++ classes can do. Including inheritance and virtual methods, when you really really need them. As for encapsulation, pointer to implementation provide a more stable, harder to cheat interface than private members. A must for stable ABIs.
C does lack generics, and I do often miss them, but templates really aren't a good solution. I don't know what a good solution looks like, I haven't looked at Zig or Rust yet.
Another thing I miss in C is a namespace system, especially when you ship libraries: makes every name longer, and you still have annoying name clashes from time to time.