Good principles needed.

This is a discussion on Good principles needed. within the C++ Programming forums, part of the General Programming Boards category; I need a list of the DOs and DO NOTs in c++. Like for example, it is good practice to ...

Good principles needed.

I need a list of the DOs and DO NOTs in c++. Like for example, it is good practice to break up your code into functions, even if the code works others -- good practice and style, you know?

One we learned in my programming class was that most programmers who program industrially do not comment their code, and the prof stressed out that you should comment A LOT -- I'm interested in things of this nature.

I need a list of the DOs and DO NOTs in c++. Like for example, it is good practice to break up your code into functions, even if the code works others -- good practice and style, you know?

One we learned in my programming class was that most programmers who program industrially do not comment their code, and the prof stressed out that you should comment A LOT -- I'm interested in things of this nature.

Yes, your code should have small functions that each do a single task each. I'm working with some ancient code that has monolithic functions that are 100-1000 lines long with almost no comments. I wish I could meet the person who wrote the code so I could "thank" them appropriately for the mess they made.

You only comment what you need to. You dont comment the obvious for one thing.

Code:

i++: // increment i

You should only comment complex things that you may find hard to understand if you re-read it in 3 months time for example and may of forgotten how somthing works. Its also usually a good idea to place a small comment above each function prototype header so you know what the function does before you read the code.

As for the dos and donts, its really programmer pecific id say, but in general these are what I follow:

DO:

Break your code into functions to maintain good readability
Use good readable indentation - 3 to 4 spaces max
Ensure you use variable names that are obvious and dont require a comment to verify it
When using classes, split it into three files if possible - ensuring implement is split from definition
Use const reference to pass an object to a function if you dont itend the function to change it
Use const as much as possible to protect data passing to and returning from a function
Only use pointers when you need to, dont use them for the sake of it
Get into the habit of using vectors over dynamic C-style arrays when possible
Practice safe computing - especially using memory allocation
Remember to use "delete" when you are finished with "new" using pointers.
Make sure your code is readable, and maintainable by another person reading it
Ensure a function preforms a suitable task and when needed returns a result

DONT:

Create a pointer and forget to initialize it a value
Same goes for a constant ^^
Use bad indentation - it makes reading a program a nightmare
(When possible ) rely on the compiler to create a default constructor - create your own as much as possible
Create functions for the hell of it - like above, make sure they preform a required task
Try to re-initalize a constant variable
Return an array/vector from a function
Forget the usefulness of references, they are "safer"pointers, but you do need pointers on some occasions of course
Use void main()
Mix C code with C++ in one program

>> When using classes, split it into three files if possible
?? What's the third?

Not sure, perhaps a reference to PIMPL?

Two resources:
Man Pages.
GIYF

Do:
Close all resources. (Memory, files, network handles, etc.) No more of this "oh, you just have to reboot it every week/day/hour/second."
Choose the appropriate container.
Treat compiler warnings as errors until you have a good reason to do otherwise.
Be aware of thread-safety, exception-safety, or any other *-safety requirements of your project/environment.

Don't:
Suffer from NIH (not invented here) - if there is an appropriate (perhaps open source) library available, use it. (This is a sub-rule of: right tool for right job)
Have your code show up on this site's front page.
Needlessly sacrifice portability. Sometimes you know you can, but if there's no good reason, don't. Wrappers can help bridge the differences between OS.
Blow resources out of the water. Just because your test environment has 2TB of everything doesn't mean the end users' will.*

[rant]* My former school system has a web-based grading/attendance software. Every six weeks, the teachers enter grade. Every six weeks, the system is brought to its knees. (Plus, my schedule every year seemed to be the output of rand(). Scheduling software should not place a senior in freshman band.) [/rant]

Suffer from NIH (not invented here) - if there is an appropriate (perhaps open source) library available, use it.

I would add a caveat to this rule. Use the appropriate library if it's active and well-supported and/or you have the source code.

My current client got burned going with a couple vendors to provide software instead of developing it in house. Two years later, we're in the process of replacing one with another 3rd party and re-writing the other. Bad support in both cases, bad quality in one.

DONT:
(When possible ) rely on the compiler to create a default constructor - create your own as much as possible

Why not? Putting an empty constructor has the same effect. What's the benefit? Sure, if you want to actually do something besides default initialization, then you need to put in a constructor, but what's the point of creating identical code to what the compiler effectively generates for you?

Why not? Putting an empty constructor has the same effect. What's the benefit? Sure, if you want to actually do something besides default initialization, then you need to put in a constructor, but what's the point of creating identical code to what the compiler effectively generates for you?

Well, I'd not say that the constructor I'd provide would be the same as the one provided by the compiler...
Consider:

Code:

struct A
{
double a;
double b;
int c;
char *d;
};

The default generated by the compiler does nothing, and the structure is left in an undefined state.
Barring some other constructor that has a purpose, a default constructor that I write would initialize those to some sane value. (Probably 0, 0, 0, NULL here)
Edit: Now, if your struct/class is a composition of other classes like vectors, lists, strings, etc - things that initialize themselves to sane values, then yeah, there's no point in writing a default constructor - the compiler's will work fine.

Here's some more rules (although I'm pretty sure they're in the book I mentioned):
- Use RAII as often as possible.
- Learn the STL thoroughly and use STL algorithms rather than writing your own.
- Don't reinvent the wheel. Look at what's already available before you write a new function/class.
- Learn the benefits/drawbacks of each STL container, and use the right STL container for the job.
- Declare variables as close as possible to the place of first use. Don't put all your variables at the top of the function, this isn't C after all.
- Don't write C+ code (i.e. C code + classes). There's a lot more to C++ than just classes.
- Learn how to use & write templates and use them whenever you need a generic solution to a problem.
- Don't write platform specific code if there's a more portable solution available.

Well, I'd not say that the constructor I'd provide would be the same as the one provided by the compiler...
Consider:

Code:

struct A
{
double a;
double b;
int c;
char *d;
};

The default generated by the compiler does nothing, and the structure is left in an undefined state.
Barring some other constructor that has a purpose, a default constructor that I write would initialize those to some sane value. (Probably 0, 0, 0, NULL here)
Edit: Now, if your struct/class is a composition of other classes like vectors, lists, strings, etc - things that initialize themselves to sane values, then yeah, there's no point in writing a default constructor - the compiler's will work fine.

I see.

That's basically a special case of "always initialize variables". But it is something to keep in mind, since with classes the code that uses the variables isn't near the code that initializes them.

I'm going to add one more thing to my list. This is a bit dependent on the software, but:

I operate two fairly large pieces of equipment. (One is controlled by a pair of Win2k PCs, the other is a small embedded computer with a touchscreen interface.) One thing I want from both: I should have a way to get extended, detailed information on its inner workings, with one or two pushes of a button. This is (or would be) great to have if I think it's acting abnormal somehow. The Win2k ones especially annoy me - if something is up, usually its response is a very cryptic 32bit error code. (App specific, not Win32 codes) Words speak louder than 32bits!

Don't cast floats directly to DWORD, cast it to long first.
Use spaces to indent not tabs, or else your code's formating becomes IDE dependent.
Align your structs! Make sure all the struct's vars are aligned on a byte evenly divisible by the size of the var itself. (I.E don't have a WORD sitting on an odd byte)
When commenting, say why your doing what your doing, not what your doing.