1) Use command line parameters to pass obvious inputs from the user.
Give the error message with the right input format, to be accepted by your code.
2) What are uintN_t types? When should we use them? How are they different from traditional integer types like short and int? When should we use unsigned values?
I found these questions in one form or the other in several discussion forums like stack overflow etc. What I can make of it is that the use is subjective between unsigned and signed int. But the rule of thumb is never mix unsigned and signed types. Now coming to uintN_t types, these are fixed types that is there size doesn't depend on the system. For example uint16_t will always be 16bits on any system. They are therefore helpful in portability.(Check this:http://notestomyselfcs.blogspot.in/2013/12/c-data-types.html)
3) Use cerr in place of cout to display error messages.
cerr, cout and clog are objects of class ostream and are used to send characters to some destination. The destination of cerr and cout is both console, but it can be changed so that all the output (cout) is diverted to some other place and errors can be kept separate. Ex: If you run a prog as ./a.out>myresult, results of cout will go to myresult and output of cerr to screen. Another difference is that cout and clog are buffered while cerr is not. What buffering means is the output is temporarily stored before being dumped on the screen in one go, this makes the output faster. cerr on the other hand is unbuffered, that is every character is put on the screen as it occurs. This is useful because if the program crashes the contents of the buffer may be lost, however cerr will still be able to give the output. This can also help in debugging by using cerr to print messages like cerr<<"Entering dangerous function"<<endl; instead of cout.
4) Use EXIT_FAILURE in place of return 1 on error.
Using return EXIT_FAILURE on failure or return EXIT_SUCCESS is a portable way of exiting a program.
5) Define every class in a .h file and import the .h file when the class is needed. Develop every class as a standalone library which can be reused.
6) Q: what is the strange #ifndef _FILE_H_
#define _FILE_H_
. ...#endif
I see in the header files? Why the strange nomenclature of using _FILE_H_?
#ifndef, #defin, #endif are preprocessor directives. The aim of above exercise is to prevent multiple declaration of variables, functions etc. when the header file is included. In simple terms, the compiler works in the following way. Before the real compilation, all the header files are included which means they are kind of copied and pasted in the code. Now if some file is imported more than once it will lead to multiple declaration error. So _FILE_H is defined when the file is included. If the file is included again, preprocessor checks that _FILE_H_ is defined and will not include the file again. Generally .h files will have the definitions and declaration and the .cpp file will have the implementation. Each .cpp file will get converted to a .o(object) file, which are then linked by the linker to produce executable
Coming to the naming part, I am confused if I can create macro variables(like _FILE_H_) which begins with an underscore. I read that identifiers starting with _ followed by capital letter or another _ are reserved for implementation (compiler or library) but still I see codes which use macro variables that start with _. Need some clarification?
7) When to create a new namespace?
We can't create two variables of the same name within a block. for ex: int x; doublex; will give error. If we are using several libraries, these libraries may have there own variables and functions which may collide with the variables we have created. To resolve this we can use namespace. Every variable defined in namespace mynamespace has to prefixed by mynamespace:: before use. You can split namespace creation in parts. Like namespace a{some variables}, some code, namespace a{some variables}
8) Use enum for clarity.
a) enum is a type that can hold integer value. there are 2 types of enums - plain and enum class. Use enum class which is type safe.
b) what is typedef enum
In C plain enums are declared like this:
enum myenum{RED,BLUE,GREEN}
Now at the time of declaration of color variable of type myenum my, you have to write:
enum myenum color = RED;
To reduce the typing effort at the time of declaration, use typedef:
typedef enum myenum
{ RED,BLUE, GREEN}
myenum;
Now just declare the variable as:
myenum color = red;
However, in C++, there is no need to do typedef.
Use typedef whenever possible for clarity. For example to represent nodes in a graph on may use:
typedef uint32_t Node; //so no Node is the data type for node numbers
9) Declare the base class destructor as virtual.
Virtual members are polymorphically available to the derived class. Therefore, if the base class destructor is not virtual and an object of base class pointing to derived class (base* b = new derived()) is created. At the time of deletion only the base class destructor is called, and thus some resources are not cleaned. (Better to look at this: http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors)
10) Use const wherever the member function is not allowed to change the member object.
11) Use trailing underscore in member variable. This is what google style guide says.
12) Always do a sanity check with function parameters. Return error via cerr<< and exit using exit(EXIT_FAILURE);
13) For creating a list use std::list
Give the error message with the right input format, to be accepted by your code.
2) What are uintN_t types? When should we use them? How are they different from traditional integer types like short and int? When should we use unsigned values?
I found these questions in one form or the other in several discussion forums like stack overflow etc. What I can make of it is that the use is subjective between unsigned and signed int. But the rule of thumb is never mix unsigned and signed types. Now coming to uintN_t types, these are fixed types that is there size doesn't depend on the system. For example uint16_t will always be 16bits on any system. They are therefore helpful in portability.(Check this:http://notestomyselfcs.blogspot.in/2013/12/c-data-types.html)
3) Use cerr in place of cout to display error messages.
cerr, cout and clog are objects of class ostream and are used to send characters to some destination. The destination of cerr and cout is both console, but it can be changed so that all the output (cout) is diverted to some other place and errors can be kept separate. Ex: If you run a prog as ./a.out>myresult, results of cout will go to myresult and output of cerr to screen. Another difference is that cout and clog are buffered while cerr is not. What buffering means is the output is temporarily stored before being dumped on the screen in one go, this makes the output faster. cerr on the other hand is unbuffered, that is every character is put on the screen as it occurs. This is useful because if the program crashes the contents of the buffer may be lost, however cerr will still be able to give the output. This can also help in debugging by using cerr to print messages like cerr<<"Entering dangerous function"<<endl; instead of cout.
4) Use EXIT_FAILURE in place of return 1 on error.
Using return EXIT_FAILURE on failure or return EXIT_SUCCESS is a portable way of exiting a program.
5) Define every class in a .h file and import the .h file when the class is needed. Develop every class as a standalone library which can be reused.
6) Q: what is the strange #ifndef _FILE_H_
#define _FILE_H_
. ...#endif
I see in the header files? Why the strange nomenclature of using _FILE_H_?
#ifndef, #defin, #endif are preprocessor directives. The aim of above exercise is to prevent multiple declaration of variables, functions etc. when the header file is included. In simple terms, the compiler works in the following way. Before the real compilation, all the header files are included which means they are kind of copied and pasted in the code. Now if some file is imported more than once it will lead to multiple declaration error. So _FILE_H is defined when the file is included. If the file is included again, preprocessor checks that _FILE_H_ is defined and will not include the file again. Generally .h files will have the definitions and declaration and the .cpp file will have the implementation. Each .cpp file will get converted to a .o(object) file, which are then linked by the linker to produce executable
Coming to the naming part, I am confused if I can create macro variables(like _FILE_H_) which begins with an underscore. I read that identifiers starting with _ followed by capital letter or another _ are reserved for implementation (compiler or library) but still I see codes which use macro variables that start with _. Need some clarification?
7) When to create a new namespace?
We can't create two variables of the same name within a block. for ex: int x; doublex; will give error. If we are using several libraries, these libraries may have there own variables and functions which may collide with the variables we have created. To resolve this we can use namespace. Every variable defined in namespace mynamespace has to prefixed by mynamespace:: before use. You can split namespace creation in parts. Like namespace a{some variables}, some code, namespace a{some variables}
8) Use enum for clarity.
a) enum is a type that can hold integer value. there are 2 types of enums - plain and enum class. Use enum class which is type safe.
b) what is typedef enum
In C plain enums are declared like this:
enum myenum{RED,BLUE,GREEN}
Now at the time of declaration of color variable of type myenum my, you have to write:
enum myenum color = RED;
To reduce the typing effort at the time of declaration, use typedef:
typedef enum myenum
{ RED,BLUE, GREEN}
myenum;
Now just declare the variable as:
myenum color = red;
However, in C++, there is no need to do typedef.
Use typedef whenever possible for clarity. For example to represent nodes in a graph on may use:
typedef uint32_t Node; //so no Node is the data type for node numbers
9) Declare the base class destructor as virtual.
Virtual members are polymorphically available to the derived class. Therefore, if the base class destructor is not virtual and an object of base class pointing to derived class (base* b = new derived()) is created. At the time of deletion only the base class destructor is called, and thus some resources are not cleaned. (Better to look at this: http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors)
10) Use const wherever the member function is not allowed to change the member object.
11) Use trailing underscore in member variable. This is what google style guide says.
12) Always do a sanity check with function parameters. Return error via cerr<< and exit using exit(EXIT_FAILURE);
13) For creating a list use std::list
No comments:
Post a Comment