You aren't using it now, but the next time you leak memory or get a double delete, you'll be begging to come back to std::vector<T>
, std::unique_ptr<T, Del>
and std::shared_ptr<T>
, which can solve those problems easily- almost trivially. That's what happens to everyone who uses C over C++, eventually, and the smarter ones just don't wait for the bugs to pop up before moving over.
Code that uses new
and delete
directly doesn't really belong in C++, it belongs in that kind of half house that we refer to as "C with Classes". That's where the language was circa 1985. It's not particularly similar to C++, circa 2011. In all likelihood, wherever you learned C++ simply didn't teach it very well- something that is unfortunately rather common- and with a better education, you would find use of these features.
Specifically, as I listed above, C++'s generic data structures and the resource-managing classes simply are fundamentally massively superior to anything C has to offer. If you want a dynamically allocated array, then use std::vector<T>
. That's a pretty common use case. If you aren't using them, then your code is at huge risk of error unnecessarily- especially resource management related. C++ can guarantee safety and re-use code in a way that C can never touch.
However, I think that you also might be expecting too much. Writing templates and operator overloads is not common for library consumers. If your code uses std::vector<T>
, you don't need to write a template to make that happen. If your code uses std::string
, nobody is forcing you to overload your operators. You only have to do those things to write std::vector<T>
and std::string
- but you can still take full advantage of them.
Polymorphism/inheritance also only has a specific use case. If your code happens to not require you to write any templates or use virtual functions, then it doesn't, and there are programs or segments of programs where you don't need to write your own templates.
Also, there's no gain in performance in C over C++.
Let's start at the beginning: mixed C and C++ code is fairly common. So you're in a big club to start with. We have huge C codebases in the wild. But for obvious reasons many programmers refuse to write at least new stuff in C, having access to C++ in the same compiler, new modules start to be written that way -- at first just leaving the existing parts alone.
Then eventually some existing files get recompiled as C++, and some bridges can be deleted... But it may take really long time.
You are ahead somewhat, your full system is now C++, just most of it is written "C-style". And you see mix of styles a problem, what you should not: C++ is a multi-paradigm language supporting many styles, and allow them to co-exist for good. Actually that is the main strength, that you are not forced to a single style. One that would be suboptimal here and there, with some luck not everywhere.
Re-working the codebase is a good idea, IF it is broken. Or if it is in the way of development. But if it works (in the original sense of word), please follow the most basic engineering principle: if it ain't broke, don't fix it. Leave the cold parts alone, put your effort where it counts. On the parts that are bad, dangerous -- or in new features, and just refactor parts to make them a bed.
If you seek general things to address, here's what worth evicting from a C codebase:
- all the str* functions and char[] -- replace them with a string class
- if you use sprintf, create a version that returns a string with the result, or puts it in the string, and replace usage. (If you never bothered with streams do yourself a favor and just skip them, unless you like them; gcc provides perfect type safety out of the box for checking formats, just add the proper attribute.
- most malloc and free -- NOT to with new and delete, but vector, list, map and other collectons.
- the rest of memory management (after the previous two points it must be pretty rare, cover with smart pointers or implement your special collections
- replace all other resource usage (FILE*, mutex, lock, etc) to use RAII wrappers or classes
When you're done with that you approach the point where the codebase can be reasonably exception-safe, so you can drop return-code football using exceptions and rare try/catch in high-level functions only.
Beyond that just write new code in some healthy C++, and if some classes are born that are good replacement in existing code, pick them up.
I didn't mentions syntax-related stuff, obviously use refs instead of pointers in all new code, but replacing old C parts just for that change is no good value. Casts you must address, eliminate all you can, and use C++ variants in wrapper functions for the remainder. And very importantly, add const wherever applicable. These interleave with the earlier bullets. And consolidate your macros, and replace what you can make into enum, inline function or template.
I suggest reading Sutter/Alexandrescu's C++ Coding Standards if not yet done and follow them closely.
Best Answer
Pointers-to-member functions make only sense if you have more than one member function with the same signature - otherwise there would be only one possible value for your pointer. But that is not possible for contructors, since in C++ different constructors of the same class must have different signatures.
The alternative for Stroustrup would have been to choose a syntax for C++ where constructors could have a name different from the class name - but that would have prevented some very elegant aspects of the existing ctor syntax and had made the language more complicated. For me that looks like a high price just to allow a seldom needed feature which can be easily simulated by "outsourcing" the initialization of an object from the ctor to a different
init
function (a normal member function for which pointer-to-members can be created).