C++ Coding Style

类别:编程语言 点击:0 评论:0 推荐:


C++ Coding Style - My Code Style
by Albert Sandberg (01 January 2003)


Introduction


Welcome. Throughout the years I've naturally changed programming languages and styles from time to time. Of course, I've been influenced by others, which has affected my own style. Nowadays, I guess I blend a couple of defined styles which are out there. However, I like how mine has developed and the reason for writing this tutorial is simply because throughout the years, I've been asked how I write code by people who don't want to take the time to find out for themselves. Or at least they just want to speed up the process :-)

With this in mind, I'm not saying that my way is the best, the most optimal or indeed any good at all. I'm saying I like the way I do it, I've seen others like it and I still get asked the questions about how to do it. I don't want a discussion of what's best because I don't care about how you write, the important thing is that you create your own style. Everybody has a mind of their own and I'm just providing the input. I'm only writing this disclamer because otherwise I know I will get flooded by mails, since everyone likes their way the very best. Thank you for understanding.

Since C and C++ syntax is quite different, I'll only cover C++ since that's really the only language I use at the moment. I think the style is pretty easy to adapt for Java, C# (C-Sharp) and other languages as well.

Why Should I Bother?


Because, when you're on a big project, you will change style over time if you don't have one made up from the start. That way, going back to code you've written months ago will not only make it harder for you to read your own code, but also mess up the files when you try to adapt it to your newest, current style.

Also, if you use the same style all over your project, it will look more professional, For instance, if you try to sell the code or show the code to get a job or similar, it will increase your chances if your code is nicely structured, named and documented.

If you specify a nice way to document (and by nice, I mean a pretty simple, fast way of writing comments) you will find yourself doing it a lot more. Suddenly you're documenting more or less each line you write and believe me, it's really nice to read documented code a couple of months after you wrote it - if it's done right. That's also not to mention others who might read it and take benefit from it.

Also it should be mentioned that if you join a project along with a few other coders and there is already a style present, don't try to change it, instead try to adapt yourself to it. Even if you don't think it's the best way of coding, the resulting project will be nicer than if you try to code your way and just badly mix up the styles. Nobody likes a wiseass :-) In other words, if you want to change style, do it on a project basis and make sure the discussions are at the start of the project.

Naming Your Files


When starting a project, think of a name for it, then make a short term for it and use it as prefix for your filenames. Since I'll be naming my project "Auto", I'll prefix all my files with auto_ : auto_car.h auto_car.cpp. And that does not mean my car has automatic gears just because Americans like it so much, its just convenient in the long run. You'll discover it too, if you haven't already.

Namespaces


First things first. I personally think it's both helpful and efficient to use namespaces in your code. If you don't know what a namespace is, simply put it's a fence around your code making it possible for you to isolate all your naming relative to your namespace. So if, for instance, your class named "Image" exists in the global namespace or in any other library, you can still use it within your namespace and access it from the outside by using NameSpace::Image, all without name conflicts!

When implementing namespaces, you wrap your classes within the following piece of code (assuming we're making the auto game):

--- auto_car.h -----------------------------------------------

// Includes first #include <stdio.h>

// Auto name space namespace Auto {

// Class goes here }

--- auto_car.h -----------------------------------------------

From this you can see two to three things about my syntax right away. I often add a comment before each line (we'll get more deeply into this a little later), I name my namespaces with a leading capital letter, and I like to put my left bracket at the end of the line instead of the following line.

The braces are probably the thing that will make most discussion here. It's almost religious amongst coders. Either you like it, or you don't. For me, it was a question of getting used to it (I was forced to use it when programming java in university, and since we were programming as a whole group, we had to use the same syntax as far as possible). However, I got to like it and now I never use anything else.

Classes


If we continue building our header file, we'll continue with this:

--- auto_car.h -----------------------------------------------

#ifndef AUTO_CAR_H #define AUTO_CAR_H

// Includes #include <stdio.h>

// Auto name space namespace Auto {

// Class goes here class Car : public VehicleType {

public: protected: private:

}; }

#endif

--- auto_car.h -----------------------------------------------

We'll leave the methods for now, and take a look at the class structure. First of all I've added redundant security by the first two lines and the last. This is made because if vector.h includes math.h and math.h includes vector.h, we have a problem. But you are probably aware of this fact already. How you name these defines is not my problem, but for all defines I use only capital letters.

The naming of the class always starts with a capital letter, and I've placed no prefix on the name (many people use conventions like CCar, I don't). The VehicleType I would normally call Vehicle I guess, but I wanted to show you how I start every new word in a name with a capital letter.

The public: -block is located at the top of the file. This is because then you look into the code, you will most often need the public (sometimes protected) interface, but never the private one. This way you won't need to scroll down a page or five just to find the public block; it's at the top, visible at the very start of the file.

I use the same naming for structs by the way, if I ever use them.

Adding Methods, Member and Parameter Variables


The naming of variables is something which also upsets people, but I think if you follow this method you will never confuse yourself :

--- auto_car.h -----------------------------------------------

#ifndef AUTO_CAR_H #define AUTO_CAR_H

// Includes #include <stdio.h>

// Auto name space namespace Auto {

// Class goes here class Car : public VehicleType {

public:

const float getSpeed(); void setSpeed(const float pSpeed);

protected: private:

float mSpeed; float mSomeVariable; }; }

#endif

--- auto_car.h -----------------------------------------------

Here you can see how I do it. For member variables, I use the prefix m. For parameters, I use the prefix p. The next letter is a capital one, and the same as every name, every new word within the same variable begins with a capital letter, such as mSomeVariable.

I use m as a prefix no matter where in my class the variable lies. Some people insist on using iVariable or fVariable to define which kind of type the variable is. For instance, iVariable would mean we're editing an integer. But then, if we want to change our type, we will need to rename that variable both in the hader file and the source file. I think that is waste of time and really never gives you any advantage. The naming of the variable could solve this issue. For instance, why would the variable "mMemberName" be an integer? I can see how people argue then it comes to something like "mSpeed". Is that integer or float representation? Well, in most cases it's crystal clear, or you will just have to check the header file.

Every core OOP programmer will probably agree with me that get/set-methods for most variables are a good thing, simply due to the fact that you might want to do more than just change the variable, for instance send a message for an update or similar.

The parameters we've already covered, but I cannot push enough that const is a really good thing. That's really what makes your code easier to use in a greater perspective and makes you find bugs before they appear. Using const correctly takes time to learn, especially with pointers, but it's a bliss then you're used to it, so use it. Now. It's a good standard!

Documenting


The above code would be worth nothing in reuse purposes if we don't comment it. As I think javadoc gives us a really good, standard way of documenting code, I think we should all use it. This is an example of how javadoc works, but it has so much to offer that it would be impossible to cover it all, so to learn more about javadoc how about visiting its homepage? However, here's a demonstration of the (partially limited) way I use it:

--- auto_car.h -----------------------------------------------

#ifndef AUTO_CAR_H #define AUTO_CAR_H

// Includes #include <stdio.h>

// Auto name space namespace Auto {

/** * Car class. Simple car in auto game :-) * * @author Albert "thec" Sandberg * @version 1.0.0 */ class Car : public VehicleType {

public:

/** * Get the speed of the car * * @return speed in miles per hour. */ const float getSpeed();

/** * Set the speed of the car * * @param pSpeed new speed of the car. */ void setSpeed(const float pSpeed);

protected: private:

// Speed of the car float mSpeed;

// Extra variables float mSomeVariable; }; }

#endif

--- auto_car.h -----------------------------------------------

That's really starting to look like something you could show your mama doesn't it? :-)

Of course, javadoc has syntax for documenting variables, extended information on which variables a method changes and a lot of other stuff. The javadoc syntax has everything you need for your documentation demands. Another very nice thing with javadoc is that doxygen (documentation creation tool for C++) handles javadoc syntax flawless. So you really can have your cake and eat it :-)

How About Other Namings?


First of all, we have enumerations. These are great to use then you have a number of modes and you really don't care about their values, just the names. One example that could be within the public:-scope of the above class:

enum eCarManufacturer {

CM_DODGE, CM_SAAB, CM_TOYOTA, CM_VOLVO, }

These will be assigned values 0,1,2,3, but you never need to know since all you care about is that none of them have the same value.

Anyway, the "eCarManufacturer" naming with the leading e is nothing that naturally falls into place, it's just something I've discovered to be my best way. However, I see the capital letters of the constant values more or less as defines, and therefore they are capitals all the way.

The prefix CM_ is used because if you have two enums in the same class, you want to be able to enter the enumeration "BLUE" both for a car and a plane, for instance. Anyway, even if conflicts are pretty rare to appear, this is a good principle.

Another thing is constant variables, such as:

static const int staticVariable=42;

I keep as normal (local, in-method) variables. BUT, (as far as I can) I never use globally declared variables like this because it's considered a bad habit and you should really get rid of it. Hence, it doesn't matter how we write it, since we will never do it anyway, right? ;-)

Now we've covered most things you will encounter, I hope. Let's have a look at a source file (.cpp)

Example Of A Source File


Let's get right to it then.

--- auto_car.cpp -----------------------------------------------

// Include header definition #include "auto_car.h"

// ===================================================== const float Auto::Car::getSpeed() {

// Deaccellerate if brakes are pushed calculateBreakPower();

// Return speed from superclass return VehicleType::getSpeed(); }

// ===================================================== void Auto::Car::setSpeed(const float pSpeed) {

// Call superclass setspeed VehicleType::setSpeed(pSpeed);

// Update car (just as an example) update(); }

// ===================================================== --- auto_car.cpp -----------------------------------------------

Hard to see in this example, but I really try to document every single line of the source code so that I (and eventually others) will see what I've done. Believe me, the simplest line of code can appear the most confusing if not properly documented a couple of months after you write it.

Many people say I document too much, but my view is that you can never do that too much!

Between the methods in the source file I like to have some kind of gross seperator. But, maybe that's just me.

本文地址:http://com.8s8s.com/it/it21933.htm