31 Dec, 2008, Lobotomy wrote in the 1st comment:
Votes: 0
For the sake of curiosity I've decided to give converting a copy of my current code from C to C++ a whirl, with the idea of learning C++ in the process. So, while I'm looking up a number of resources online to give me help on the matter, I'm curious to hear of any advice, information resources, etc and so-forth that others here at Mudbytes may have on the matter. I.e, things to look for, things I should know, things I might want to know, etc etc.

Of course, I plan on this thread being rather large and not only being for my own sake. If there's some bit of advice pertaining to C to C++ transitions that could be beneficial in general to others then by all means post it. There may already be a thread pertaining to this on Mudbytes that I'm not aware of, although considering that search turned up nothing on a simple "C++" query I'm going to assume that the search function hates me and/or there isn't such a thread yet.

Additionally, as I've noted before I've made use of C's C99 features and GNU extensions to C99 so if there are particular bits pertaining to the conversion of such code to their C++ equivalents (if there are any such equivalents, anyways) that'd be great to hear as well.
31 Dec, 2008, Lyanic wrote in the 2nd comment:
Votes: 0
The transition from C to C++ on an already extensively developed game is a slow and painful one, especially if you want to continue active development (as opposed to delaying all future developments for 6-18 months during the conversion process). I'm not sure what type of game you have, but if it's a Diku - I have a few suggestions from my own experience. The first two things I'd advise doing (aside from changing the file extensions, headers and library inclusions and making sure it compiles on a C++ compiler) are swapping out all the C-style strings for string types from the string library and then start incorporating STL algorithms for all the searching/sorting/hashing/etc done by the MUD. After that - rewriting memory allocation methods would be great (new and delete FTW).
31 Dec, 2008, Lobotomy wrote in the 3rd comment:
Votes: 0
Lyanic said:
The transition from C to C++ on an already extensively developed game is a slow and painful one, especially if you want to continue active development (as opposed to delaying all future developments for 6-18 months during the conversion process). I'm not sure what type of game you have, but if it's a Diku - I have a few suggestions from my own experience. The first two things I'd advise doing (aside from changing the file extensions, headers and library inclusions and making sure it compiles on a C++ compiler) are swapping out all the C-style strings for string types from the string library and then start incorporating STL algorithms for all the searching/sorting/hashing/etc done by the MUD. After that - rewriting memory allocation methods would be great (new and delete FTW).

I neglected to mention it yet again; my bad. The code I'm working on is a small, custom codebase of my own design that is derived from SocketMUD. That said, I still appreciate the advice.
31 Dec, 2008, Lyanic wrote in the 4th comment:
Votes: 0
Lobotomy said:
I neglected to mention it yet again; my bad. The code I'm working on is a small, custom codebase of my own design that is derived from SocketMUD. That said, I still appreciate the advice.


Well, most (if not all) of the advice I gave is still valid. For instance, any MUD written in C is obviously going to be using C-style strings. The efficient algorithms in STL aren't available in C (unless you wrote them yourself). Furthermore, new and delete (more efficient memory allocation/deallocation) aren't available in C. This thread actually has me interested now in input from others who have tried C to C++ conversions before. Post people!
31 Dec, 2008, Lobotomy wrote in the 5th comment:
Votes: 0
Lyanic said:
Well, most (if not all) of the advice I gave is still valid.

I know. Hence "That said, I still appreciate the advice."
31 Dec, 2008, David Haley wrote in the 6th comment:
Votes: 0
Well, it depends on what exactly is meant by "conversion from C to C++". If you mean encapsulate absolutely everything in classes and replace all containers with STL equivalents, then yes, it'll take a long while. Why do that, though? A helpful tip about refactoring code is to write all new code "correctly", and refactor old code as you touch it. So don't spend a huge chunk of time on a witch hunt fixing code that is hardly used.

There are some things you need to know about, though…

- There are C++ keywords that you cannot use as variable names. The one that causes the most problems is probably "class". Many people replace it with "Class". I don't like that, as it breaks naming convention. But you have to replace it with something. These are very easy: the compiler will complain at you until you fix all instances.

- If you allocate structures with 'malloc' (or variants) any member objects will not be initialized correctly – i.e., their constructor will not be called. This can vary from not-so-bad to Really Very Bad. Although I argued above against making a mass conversion, replacing malloc/free with new/delete early on will save you many headaches later as you forget that structures weren't actually initialized, so that nested member actually contains bogus data. This is a pretty tricky issue so it's important to get it right.

- While std::string is extremely helpful, it doesn't implement full string sharing. (Most implementations are smart enough to figure out share-on-copy, which is a pretty good start.) You might want to look into shared string objects. (Plug: I have a library available for download.)

- Unlike passing around char*, which is almost as efficient as can be, if you pass around std::string objects you're copying the whole string every time. Pass-by-reference is a very useful convention here. Instead of f(std::string s), declare f as: f(const std::string& s). This way, the parameter passing is as efficient as a pointer, and you preserve integrity of the caller's string. (Of course, if you want f to modify s, you wouldn't declare it as const.)

- You don't really need to go nuts with the STL. Use it where it helps you, but do not feel compelled to use it everywhere you possibly could. You'd just be wasting your time.

- Same goes for classes. They're very helpful, but there is no inherent value in renaming every 'struct' to 'class', making variables private, and adding getters/setters for everything. My strategy for a gradual conversion is that as soon as I decide to start refactoring a struct, I go from struct to class and then make all members public (so that I don't have to go modify a ton of code). Then, I take just the member(s) I'm dealing with – for example, the character name – and make them private. Then, I add getters/setters.
Case study: I wanted to give characters a "stage name" so that bards could, in special rooms, take on any name for the sake of performance. But I didn't want the horrible ugliness of having every single reference to character name in 'act' etc. test whether or not a stage name was active. The solution? Add a 'getter' function on the character class that returns the normal or stage name as appropriate. (In fact, it is slightly more complicated, as some routines need the actual name. So, I added getName and getRealName, with the latter always returning the actual name.)


I cannot stress enough that doing an initial mass conversion will not really be helpful if you are working with a very large codebase. I believe though that you mentioned you're working with a relatively small base, in which case it makes sense to encapsulate things properly now before the whole system gets too large. But in general, I repeat a very important time-saver for refactoring: write new code correctly, and fix old code as you come across it while writing new features.
31 Dec, 2008, David Haley wrote in the 7th comment:
Votes: 0
Some more notes on things posted while I was writing:

- Don't use new/delete instead of malloc/free thinking your gain is efficiency. Your gain is that member field constructors are called. The efficiency gain, if any, is implementation dependent and secondary.

- STL algorithms are not necessarily more efficient than C library algorithms; it's just that they operate nicely on other STL objects like containers. Don't convert your logic to use STL algorithms merely for the sake of efficiency.

A general theme: efficiency is not your highest goal. Your gain will be small, if indeed there is any at all, and you will be spending your very valuable programming time on that instead of adding new features or improving code architecture.
31 Dec, 2008, Lyanic wrote in the 8th comment:
Votes: 0
DavidHaley said:
A general theme: efficiency is not your highest goal. Your gain will be small, if indeed there is any at all, and you will be spending your very valuable programming time on that instead of adding new features or improving code architecture.


Except I consider readability and writability [sic] a part of efficiency (not merely computational resource usage). A lot of the changes from C to C++ improve these aspects, allowing future implementations to be accomplished more quickly.
31 Dec, 2008, David Haley wrote in the 9th comment:
Votes: 0
Well, ok, except that for the purpose of clear communication it would be easier to not overload the terms that way. :wink: If you mean to speak of readability etc., you should either explicitly qualify efficiency as "programmer efficiency" or use another word like "maintainability" or something like that. Efficiency used on its own is almost always pretty clearly used to mean computational efficiency, so it's probably easiest to stick to that so that we all understand each other. I certainly agree with you that letting developers make better use of their time is very valuable, and C++ helps you do that over C.
0.0/9