Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Thursday, May 09, 2013

Simple and Basic C++ Coding Conventions

1. Introduction



Most basic concept of C++ style rule is Use common sense and always be consistence inside the project. Most common logic of software development is that 10% of the cost of a project goes into writing code, while more than 50% is spent on maintaining it.
Think about the trade-offs between ease-of-programming now vs. ease-of-maintenance for the next 5 to 10 years when you consider the recommendations presented here.
The establishment of a common style will facilitate understanding and maintaining code developed by more than one programmer as well as making it easier for several people to cooperate in the development of the same program. The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you are saying, rather than on how you are saying it. This document present global style rules here so people know the vocabulary. But local style is also important. If code you add to a file looks drastically different from the existing code around it, the discontinuity throws readers out of their rhythm when they go to read it. Try to avoid this. If you are editing code, take a few minutes to look at the code around you and determine its style.


2. Coding conventions


2.1. Files

  1. There should be one include class declare header file for each source code file.
  2. Each include file should describe a single class or tightly integrated set of classes.
  3. The name of the file should be the name of the class contained in the file without the leading "C". And file names should begin with lower case letters.
  4. File names should limited up to 30 characters.
  5. File names and directory paths should not contain blanks, parentheses "(", or crazy characters
  6. File header comments shall be placed at the top of each file stating the name of the file and comments on the file contents [Appendix 01].
  7. Do not use filenames that already exist in STL Fine names should be lowercase and words separate by underscore sign. 
  8. Each project should have a readme.txt file

2.1.1. Header Files(.hpp)

  1. Header files should only to contain definitions and NOT instantiations. Thus the include file can be used in multiple files.
  2. All header files should have #define guards to prevent multiple inclusions.
  3. The format of the symbol name should be FILENAME_H_
  4. Do not use #pragma once.
  5. If a class in a header file does not need to know the size of a data member class or does not need to use the class's members then forward declare the class instead of including the file.
  6. When including use standard order for readability and to avoid hidden dependencies: C library, C++ library, other libraries' .hpp, your project's .hpp.
  7. Within each section, includes should be ordered alphabetically.
  8. Do not include files with full path. Include statements should be documented, telling the user why a particular file was included.
  9. If the file includes a class used by the class then it's useful to specify a class relationship.
  10. C++ header files often use the suffix ".hpp" while "C" header files use ".h" suffix.
  11. Avoid the use of "namespace" in the ".hpp" include file.

2.1.2. Source file(.cpp)


  1. C++ source files should have a .cpp extension. Each source file should always have a header file with same name and a .hpp extension.
  2. The source file defines code and It instantiates definitions defined in the include file.

2.1. Namespace


  1. Unnamed namespaces in .cpp files are encouraged.
  2. Do not use a using-directive outside the classes in .hpp files.
  3. You may use a using-declaration anywhere in a .cpp file, and in functions, methods or classes in .hpp files.
  4. Do not use unnamed namespaces in .hpp files.
  5. Namespaces wrap the entire source file after includes, definitions/declarations, and forward declarations of classes from other namespaces.
  6. Do not use namespace aliases are outside of the named namespace in .hpp.
  7. Namespace names should be all lower-case.

2.2. Class and structures

  1. Be sure to add virtual to the base class destructors.
  2. Access modifier sequence should be public, protected then private and the declaration order should be
    • Typedefs and Enums 
    • Constants (static const data members)
    • Constructors 
    • Destructor 
    • Methods, including static methods
    • Data Members (except static const data members)
  3. Avoid doing complex initialization in constructors (in particular, initialization that can fail or that requires virtual method calls). 
  4. When redefining an inherited virtual function, explicitly declare it virtual in the declaration of the derived class
  5. If class doesn’t have other constructors you must define a default constructor (one that takes no arguments) and use to initialize the members.
  6. Use the keyword explicit for constructors with one argument except copy constructor.
  7. Do not overload operators except in rare, special circumstances

2.3. Functions

  1. Define functions inline only when they are small, say, 10 lines or less.
  2. Try to keep function short and simple (around 40 lines).
  3. When defining a function, parameter order is: inputs, then outputs.
  4. Write some descriptive comments before every function, telling the user what you did and why.
  5. Use completely global functions rarely and put nonmember functions in a namespace avoid polluting the global namespace.
  6. Place a function's variables in the narrowest scope possible, and initialize variables in the declaration.
  7. Function names should be descriptive; eschew unknown abbreviation, should be "command" verbs.
  8. Regular functions name should start with a capital letter and have a capital letter for each new word. No underscores.
  9. Accessors and mutators (get and set functions) should match the name of the variable they are getting and setting


2.4. Variables

  1. Variable names should be descriptive; eschew unknown abbreviation types and should be nouns.
  2. Name should be lowercase and use underscore to combine nouns (my_variable
  3. Class member variables have trailing underscores (my_variable_)
  4. Declare object variable used in a loop outside that loop.
  5. Variables are to be declared with the smallest possible scope.
  6. Avoid local variable definitions that override (hide) variables defined at higher levels.
  7. Try not to use Static or global variables of class type.
  8. Consider to use const in possible locations.
  9. Try not use variable length arrays, use vectors instead.
  10. Data members in structs should be named like regular variables without the trailing underscores that data members in classes have.
  11. Use prefix g_ with global variables. But discourage to use global variables.
  12. Use prefix c_ for constants variables.
  13. Do not use Hungarian notation
  14. A global variable would be instantiated in the ".cpp" file and NOT the ".hpp" file

2.5. Comments

  1. When writing your comments, write for your audience: the next contributor who will need to understand your code. Be generous.
  2. Start each file with license boilerplate, followed by a description of its contents with header comments.
  3. Do not duplicate comments in both the .hpp and the .cpp.
  4. Every class definition should have an accompanying comment that describes what it is for and how it should be used.
  5. Every function declaration should have comments immediately preceding it that describe what the function does and how to use it.
  6. What the inputs and outputs are should comment in function definition.
  7. If there ant special things to mention about the function, It should comment above the function definitions (How it does the job).
  8. Each class data member (also called an instance variable or member variable) and global variables should have a comment describing what it is used for.
  9. In your implementation you should have comments in tricky, non-obvious, interesting, or important parts of your code. But not everywhere.
  10. Note that you should never describe the code itself. Assume that the person reading the code knows C++.
  11. Use TODO comments with your email for code that is temporary, a short-term solution, or good-enough but not perfect. (TODO(kl@gmail.com): Need to implement thread safe.)


2.6. Formatting

2.6.1. Function declaration and definition

  1. Simple function
    ReturnType ClassName::FunctionName(Type par_1, Type par_2){
      DoSomething();
      ...
    }
  2. With long argument list.
    ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
        Type par_1
        Type par_2,
        Type par_3){
      DoSomething();
      ...
    }
    
  3. The return type is always on the same line as the function name.
  4. The open parenthesis is always on the same line as the function name.
  5. There is never a space between the function name and the open parenthesis.
  6. There is never a space between the parentheses and the parameters.
  7. The open curly brace is always at the end of the same line as the last parameter.
  8. The close curly brace is either on the last line by itself or on the same line as the open curly brace.
  9. All parameters should be named, with identical names in the declaration and implementation.
  10. All parameters should be aligned if possible.
  11. If some parameters are unused, comment out the variable name in the function definition for future use.


2.6.2. Function call

  1. Simple function call
    bool retval = DoSomething(argument1, argument2, argument3);
  2. If the function has many arguments, consider having one per line if this makes the code more readable.
    bool retval = DoSomething(argument1,
                              argument2,
                              argument3,
                              argument4);
    

2.6.3. Conditionals

  1. Simple condition.
    if(condition){ 
      ... 
    }else if(...){ 
      ...
    }else{
      ...
    }
  2. Short conditional statements may be written on one line if this enhances readability.
    if (x == kFoo) return new Foo();
    if (x == kBar) return new Bar();
    

  3. Do not write short conditional statement when the “if” statement has an “else”.
    if (x == kFoo){
      return new Foo();
    }else{
      return new Bar();
    }
    

  4. When you have a Boolean expression that is longer than the standard line length, break up  to the lines.
    if (this_one_thing > this_other_thing &&
        a_third_thing == a_fourth_thing &&
        yet_another && last_one) {
        ...
    }

2.6.4. Loops and switch statements

  1. Simple switch always should have default and break.
    switch (var){
      case 0:
        ...
        break; 
      case 1:
        ...
        break; 
      default:
        assert(false); 
    }

  2. If the content of the cases are too long should use curly brackets.
    switch (var){
      case 0:{
        ...
        ...
        ...
        ...
        break;
      } 
      default: {
        assert(false);
      }
    }
    
  3. Simple while loop.
    while(condition){
      ...
    }
  4. Simple for loop.
    for(int i=0; i<10; ++i){
      ...
    }

  5. Empty body loops should use “continue” or “{}”, but not single semicolon.
    while(condition){} not while(condition);
    

2.6.5. Pointer and Reference Expressions

  1. When declaring a pointer variable or argument, you may place the asterisk adjacent to the variable name.
    char *a;
    const string &str;
    

2.6.6. Preprocessor Directives and Macros

  1. Preprocessor directives are within the body of indented code or begin of the file; the directives should start at the beginning of the line.
  2. Macro names should name with all uppercase and underscores.

2.6.7. Class

  1. Any base class name should be on the same line as the subclass name, subject to the 80-column limit.
    class MyClass : public OtherClass {
      ...
      ...
    };

  2. Type names (for classes, structs, typedefs, and enums) start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass.
  3. Constructor initializer lists can be all on one line or with subsequent lines if there are more things to initialize.
    MyClass::MyClass(int var) : var_(var), var2_(var + 1) {}
    
    
    MyClass::MyClass(int var)
    : var_(var),
      var2_(var + 1),
      var3_(var + 2)  {}

  4. The contents of namespaces are should not indented.

    namespace {
    void foo() {
      ...
      ...
    }
    }

2.6.8. Horizontal Whitespace

  1. Keep white spaces both sides of operator like =, +, -, / , && according to the place it uses.
    x = 0;
    x = -5;
    ++x;
    if (x && !y)
    v = w*x + y/z;
    v = w * (x + z);
    

  2. Keep space after each semicolon or colon exist before the line end.
    for ( ; i < 5 ; ++i)
    for (auto x : counts) {)
    

2.6.9. Vertical  Whitespace

  1. Do not waste new lines.
  2. Put one blank line between functions.
  3. Do not leave blank lines at the beginning or end of a function.

2.7. Other

  1. Use C++ casts like static_cast<>(). Do not use other cast formats like int y = (int)x; or int y = int(x);
  2. Use prefix form (++i) of the increment and decrements operators with iterators and other template objects.
  3. Use const whenever it makes sense and consider making data members const whenever they do not need to be modified after construction.
  4. Try not to use unsigned integers.
  5. Use 0 for integers, 0.0 for reals, NULL for pointers, and '\0' for chars when necessary.
  6. Use sizeof(variable) instead of sizeof(type) when you need to get the size of a variable.
  7. Each line of text in your code should be at most 80 characters long.
  8. Avoid the use of numeric values or hardcode values in code; use symbolic values instead.
  9. Do not allocate memory and expect that users will de-allocate it later.

3. Appendix -01

/*******************************************************************
File:  filename.ext
Author:  Author Name
E-Mail:  author@yourcompaney.com
Description:  Here is the area that should describe what is the usage of this class and what is the functionality of the class and the important things that need to mentions. 
Language:  C++
Version: 1.0
Limitations: none/some (i.e: limitations such as file size string lengths etc..)
Copyright: Your Companey
Thread Safe:  yes/no  
Extendable:  yes/no  
Platform Depend:none/some (i.e.: Linux/Intel, Windows/Intel, Solaris/SPARC)
Change History:
--------------------------------------------------------------------
Date   Author   Description
YYYY-MM-DD  Author Name  What is the improvement or change have done because of which reason
*******************************************************************/



Referance

  1. The C++ Programming Language,  By  Bjarne Stroustrup  
    Publication Date: June 30, 1997 | ISBN-10: 0201327554 | ISBN-13: 978-0201889543 | Edition: 3
  2. C++ Coding Standards: 101 Rules, Guidelines, and Best Practices,  By Herb Sutter  and Andrei Alexandrescu
    Publication Date: November 4, 2004 | ISBN-10: 0321113586 | ISBN-13: 978-0321113580 | Edition: 1
  3. http://cpp.capibara.com
  4. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
  5. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html

Thursday, March 28, 2013

Types of constant pointers in C++



In C++ there are basic three types of constant pointers exist.
  1. Pointer that pointed to some constant data.
  2. Pointer that constantly pointed to some memory location.
  3. Pointer that constantly pointed to some constant data.

Pointer that pointed to some constant data.

const datatype * pointerName;
dataType const * pointerName

Here the pointer is pointing to some constant data. That means the data pointed by pointer cannot edit using the pointer. As example if pointer "p" pointing to some string "This is a constant string", The pointer "p" cannot use to edit the content "This is a constant string"


Example:If you try with this peace of code

#include <iostream>
using namespace std;

int main(){
 const char * const_data_pointer_1 = NULL;
 const_data_pointer_1 = "This is a constant string";
 const_data_pointer_1[10] = 'A';
 return 0;
}

C++ compiler shows error like

error C3892: 'const_data_pointer_1' : you cannot assign to a variable that is const


Pointer that constantly pointed to some memory location.

dataType * const  pointerName

Here the pointer behave a content, It means once initialize the pointer it cannot change the memory location it pointing to. In previous type, the content pointed by pointer behave as constant. by here the content pointed by pointer allow the edit but the memory location pointed by the pointer cannot change.

Example:If you try with this peace of code.


#include <iostream>
using namespace std;
int main(){
 char * const cont_pointer = "This is not a constant string"; 
 cont_pointer = "This new memory location not allow to point";
 system("pause");
 return 0;
}

C++ compiler shows error like

error C3892: 'cont_pointer' : you cannot assign to a variable that is const


Pointer that constantly pointed to some constant data.

const dataType * const pointerName;
dataType const * const pointerName;

This type pointer also a constant pointer, It means cannot change the memory location pointed by this pointer. And also the content pointed by the pointer also constant, It means the content pointed by the pointer also not allow the alter.

Example:If you try with this peace of code.

#include <iostream>
using namespace std;
int main(){
 char const * const cont_pointer = "This is not a constant string";
 cont_pointer[10] = 'A';
 cont_pointer = "This new memory location not allow to point";
 system("pause");
 return 0;
}

C++ compiler shows error like.
error C3892: 'cont_pointer' : you cannot assign to a variable that is const
error C3892: 'cont_pointer' : you cannot assign to a variable that is const

Thursday, December 06, 2012

Unit test for unmanaged C++ in Visual Studio


Bugs free software is a dream of every person who involve in software development process. But with the today complex software systems and even more featured requirements , it is quite a challenge to overcome this specific expectation.
There are number of methodologies and tools for bug tracking, debugging, error tracing and various level to testing. But as the developers unit testing and integrated testing are the most important kind of testing that require to implement a bug free software. So in this article I'm  going to show you some tips and methodologies of unit testing.   As C++ developers knows unit testing for unmanaged C++ is a quit cumbersome and there is no standers way to do the unit testing for development environment. Normally expert developers prefers the TDD (Test driven development) for error less software and as a confident development method  that support to maintain and extend the already developed software.

Most of the Unmanaged C++ developers  developers mostly use some kind of third party Unit Test frame-works such as 'Boost Test', 'Google Test' or 'cppUnit'  even they works on windows environment. Actually these unit testing frameworks have some unique features and capabilities than .NET unit testing framework, such as object mocking and various Assert rules. But when you are working with Visual Studio IDE, using .NET unit testing framework may easy to use and compatible than other unit testing frameworks. But even some developers uses .NET unit testing capability for MFC or ATL projects (Manage C++), Most of them  don't have idea how to use it with unmanaged C++ development. But If  you are involving in DLL or LIB development using C++ it is easy to do unit testing by adding the static or dynamic library as reference to the testing project.

But in this article I'm going to introduce you how the set-up unit testing for  for Win32 console application  (Unmanaged C++) (But even this is possible with Win32 windows applications) in Visual Studio 2010 with Windows operation system. Even I describing this for Visual Studio 2010, It may applicable with other versions such as 2012,2008 or 2005. So lets start as step by step guide from here.

Today I'm going to develop a simple calculator with unit testing for the functionality.

Add Main Project

1. Open visual studio 2010 and Create a new project by using 'File' -> 'New'
2. In new project window go to right hand side panel -> select Visual C++ -> select Win32
3. In the Right hand side panel select 'Win32 Console Application'
4. Type 'calculator' in Name text field bellow and select the location as you need.


5. Then next window (Win32 Application Wizard) just click next
6. Then next window select 'Empty Project' and keep setting as this image. then click finish



So this is our main project and main method should be in this project for initiate the application.

7. In the Solution explorer expand calculator -> right click on 'Source File' -> 'Add' -> 'New Item' -> select 'C++ File (.cpp)'
8. Type the name 'main' in Name text box and click add


Add Lib Project

1. Right click Solution in 'Solution explorer' and select 'Add' -> 'New Project'
2. Next window in left pane select Win32 and in right pane select 'Win 32 Console Application'
3. Type 'calculator_lib' in Name text box and click ok.
4. In next window just click next
5. In next window select Static library and keep other setting as image. Then click finish.




Add Test Project

1. Same as above right click Solution in 'Solution explorer' and select 'Add' -> 'New Project'
2. Next window left hand panel select 'Visual C++'->'Test'
3. Type calculator_test in Name text box
4. Click OK

Now your solution explorer should have three project and It should looks like this image


Configurations Test Project 

1. Right click calculator_test project and select properties'
2. In left hand panel select 'Common Properties' -> 'Framework and Referance'
3. In right side panel click 'Add New Reference' button at bottom
4. Select 'Project' tab then select  'calculator_lib' and  click OK
5. Left side panel select 'Configuration Properties' then 'General'
6. In top left combo box select 'All Configurations
7. Change the Target Name from 'DefaultTest' to 'CalculatorTest'
8. Then expand 'C/C++' and select 'Genaral' in left hand panel
9. In right hand panel there is a entry 'Additional Include Directories' paste the bellow text there

$(SolutionDir)\calculator_lib;%(AdditionalIncludeDirectories)

10. change 'Common Language Run Time Support' as 'Common Language RunTime Support (/clr)' in Right side panel and click OK

Configurations Main Project 

1. Right click on calculator project and select properties.
2. In top left combo box select 'All Configurations
3. In left hand panel select 'Common Properties' -> 'Framework and Referance'
4. In right side panel click 'Add New Reference' button at bottom
5. Select 'Project' tab then select  'calculator_lib' and  click OK
6. Then expand 'C/C++' and select 'Genaral' in left hand panel
7. In right hand panel there is a entry 'Additional Include Directories' paste the bellow text there

$(SolutionDir)\calculator_lib;%(AdditionalIncludeDirectories)

8. Click OK


C++ Coding

1. Go to solution explorer and expand the calculator project
2. open the 'main.cpp' file and paste the following code on it.

#include <iostream>
using namespace std;
int main()
{
 cout << "This is my first Unit Test for unmanaged C++ application";
 return 0;
}
3. Click Ctl+F7 to build the solution and solution should build with three projects as bellow image.



4. Right click the 'calculator_lib' project in solution explorer and click 'Add'-> 'Class'
5. Select 'C++ Class' from right panel in next window and click add.
6. In next window add 'basic_calculator' in 'Class name' text box and click finish.


7. Open' basic_calculator.h' file and replace the following code in to it
#pragma once
class basic_calculator
{
public:
 basic_calculator(void);
 ~basic_calculator(void);
 int add(int a,int b);
 int minus(int a,int b);
 int multiply(int a,int b);
 int devid(int a,int b);
};

8. Open 'basic_calculator.cpp' file and replace the fallowing code in to it


#include "StdAfx.h"
#include "basic_calculator.h"
basic_calculator::basic_calculator(void)
{
}
basic_calculator::~basic_calculator(void)
{
}
int basic_calculator::add(int a,int b)
{
 return a+b;
}
int basic_calculator::minus(int a,int b)
{
 return a-b;
}
int basic_calculator::multiply(int a,int b)
{
 return a*b;
}
int basic_calculator::devid(int a,int b)
{
 return a/b;
}

Adding test case
1. Right click the calculator_test project and click 'Add' then 'New Test'
2. In next window select 'UnitTest' and add 'basic_calculator_test' for 'Test Name' text field and click OK


3. Open basic_calculator_test.cpp file and clear unawareness comment, include 'basic_calculator.h' file and create a pointer 'by basic_calculator' class

Note: Actually here I'm showing how to write vary basic few test cases for your start. Later you can find your own journey in unmanaged C++ unit testing.


4. Change test method name to addTest and write a test case for 'add' functionality using assert
5. Same as this add another three test cases for remaining functionality also.
6. So finally your  'basic_calculator_test' should be like this

Note: Mostly IntelliSense not supporting for C++ Test project in Visual Studio 2010

#include "stdafx.h"
#include "basic_calculator.h"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;


namespace calculator_test
{

[TestClass]
public ref class basic_calculator_test
{
private:
TestContext^ testContextInstance;
basic_calculator* test_calculator;

public:
property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
{
 Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
 {
  return testContextInstance;
 }
 System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
 {
  testContextInstance = value;
 }
};

[TestMethod]
void addTest(){Assert::AreEqual<int>(6, test_calculator->add(4,2));};

[TestMethod]
void minusTest(){Assert::AreEqual<int>(2, test_calculator->minus(4,2));};

[TestMethod]
void multiplyTest(){Assert::AreEqual<int>(8, test_calculator->multiply(4,2));};

[TestMethod]
void devidTest(){Assert::AreEqual<int>(2, test_calculator->devid(4,2));};

[TestMethod]
void addTestForFail(){Assert::AreEqual<int>(5, test_calculator->add(3,3));};
};
}

7. Now you finish creating test cases for your basic_calculator.
8. Right click on "Soloution 'calculator'" in project explorer and click properties
9. Next window select calculator_test as 'Single startup project' and click ok


10. Then press Ctl+F7 to build the project and then F5 to run.
11. You will see your Unit test are running in the bottom and you can see the result in 'Test Result' Window

12. So as we expected four of our unit test passed and one failed you can write more advance test cases by improving your knowledge and  reading about Assert functions.

Building Application
1. Open main file under 'calculator' project and replace with fallowing code.


#include <iostream>
#include "basic_calculator.h"

using namespace std;

int main()
{
cout << "This is my first Unit Test for unmanaged C++ application" << endl;

basic_calculator* my_calculator = new basic_calculator();
cout << "4 + 2 =" << my_calculator->add(4,2) << endl;
cout << "4 - 2 =" << my_calculator->minus(4,2) << endl;
cout << "4 * 2 =" << my_calculator->multiply(4,2) << endl;
cout << "4 / 2 =" << my_calculator->devid(4,2) << endl;

system("pause");
return 0;

}

2.Right click on "Soloution 'calculator'" in project explorer and click properties again
3. Next window select 'calculator' as 'Single startup project' and click ok
4. Build the project and run then you can see the result


Congratulations!  Now you know how to create unit test for unmanaged C++ applications. So need to do more studies to be a expert Unit test writer. I'm putting her some resource for your referance

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assert.aspx
http://msdn.microsoft.com/en-us/library/te3ecsc8.aspx

Sunday, November 18, 2012

Tab key not working in Visual Studio 2010

If you face the not working tab key in the visual studio editor. Here shows how to make Tab key work.
  1. Go to Tools->Options->Text Editor->C/C++->Formatting
  2. Find the "Indentation" group on right side.
  3. Find the Automatic Indentation On Tab.
  4. Make it false.
  5. Enjoy the Tab key :)

If you are working with some other language, Then select the appropriate language instead of C/C++