1. Casting
2. Class
3. Converting
4. Dependencies between .cpp and .hpp files
5. GNU/Linux related
6. Operator
7. Plain Pointer
8. Powerset
9. Smart Pointer
10. Statements
11. String
12. Template
13. Tricks
14. Vector
1.1. Explicit constructor
If a constructor is declared as explicit, no any hidden conversion is possible.
explicit MyConstructor(String s);
MyConstructor("hello"); // this is allowed
MyConstructor("c"); // this is allowed
MyConstructor('c'); // this is forbidden (int -> string not allowed)
2.1. Access
The members and methods are accessible from external:
public
The members and methods are accessible ONLY from the owner class:
private
The members and methods are accessible from the owner class and the derived classes:
protected
2.2. Declaring a method as const
When a method is declared as const, it can't modify the values of the class members.
class MyClass
{
int a;
int myMethod() const
{
return a; // this is allowed
return a++; // this is forbidden
}
}
2.3. Declaring a variable or a parameter as const
When a variable or a parameter is declared as const, it can't be mofiefied.
void myMethod(const int a)
{
cout << a; // this is allowed
cout << a++; // this is forbidden
}
2.4. Deriving a class
Class Base
{
public:
void myMethod() const = 0;
}
Class MyClass : public Base
{
public:
void myMethod() const
{
return;
}
}
In this case, MyClass is derived from Base.
2.5. Inline
Creating a method as
inline
doesn't create a subroutine but puts the code in each points where there is a call to such methods.
2.6. Passing parameters to a method
Generally:
A parameter should be declared as "const" only when it is a pointer or a reference.
A parameter should be declared as reference only if it size is bigger than 4 byte (call by reference).
int
bool
const std::string&
const Object&
const Object*
2.7. Static
A class, method or member declared as static will be instanciated only once.
For all non static kind, the compiler inserts a pointer to the owner class (the "this" pointer), so that they can be identified in a unique way.
For all static kind, this pointer doesn't exist because there is only one instance.
2.8. Virtual
Generates non rewritable code:
myMethod()
Generates rewritable code with default code:
virtual myMethod()
Don't generate any code. This code MUST be overwritten:
virtual MyMethod() = 0
3.1. Integer to ASCII
A good replacement of the itoa function is the following:
ingeter = 10;
char buffer[50];
sprintf(buffer, "%d", integer);
4.1. Include
When a header should be included:
- need of base class
e.g.: boost::noncopyable needs #include<boost/utility.hpp>
- need of a typedef
- need of a template
e.g.: std::string<> needs #include<string>
When a header shouldn't be included:
- need of a pointer, reference or smart pointer of a class or struct
- need of a enum
In these cases, the needed type must be forward declared and the include must be done in the .cpp file.
5.1. Checking for Linux version
To check for the Linux version (kernel) the following code can be used:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
mycode();
#endif
6.1. Overloading
Replace the default operator with a self defined
int operator+(int a, int b)
{
return a * b;
}
a = 3;
b = 4;
cout << 3 + 4
The output is:
12
7.1. Instanciating a plain pointer
Plain pointer should not use constructors:
MyStruct* myPtr = new MyStruct; // right
MyStruct* myPtr(new MyStruct); // wrong
Instead, smart pointers should use them:
boost::shared_ptr<MyStruct> pTemp(new MyStruct); // right
8.1. Using powerset
Consult the help for std::bitset.
9.1. Resetting a smart pointer
boost:shared_ptr<MyClass> myPtr(new MyClass);
myPtr.reset();
9.2. Setting a smart pointer
During the instance:
boost::shared_ptr<MyClass> pSmartMyClass(new MyClass);
Later:
boost::shared_ptr<MyClass> pSmartMyClass;
MyClass* pMyClass = new MyClass;
pSmartMyClass.reset(pMyClass);
9.3. Returning a smart pointer
bool myFunction(boost::shared_ptr<MyObject> pMyObject)
{
MyObject* pTemp(new MyObject);
pMyObject.reset(pTemp);
}
boost::shared_ptr<MyObject> pMyObject(new MyObject);
myFunction(pMyObject);
9.4. Returning more smart pointers
Possibility 1 (esiest):
void method1(
boost::shared_ptr<Class1>& p1,
boost::shared_ptr<Class2>& p2
)
{
...
p1.reset(new MyClass1); // works sure
// p1 = boost::shared_ptr<Sub1>(new MyClass1); // should work
p2.reset(new MyClass2);
...
}
boost::shared_ptr<Class1> p1((Class1*)0);
boost::shared_ptr<Class2> p2((Class2*)0);
method1(v1, v2);
Possibility 2:
std::pair<boost::shared_ptr<Class1>, boost::shared_ptr<Class2> > method2()
{
...
return std::pair<boost::shared_ptr<Class1>, boost::shared_ptr<Class2> >(new Sub1, new Sub2);
}
9.5. Using smart pointers with plain pointers
Plain pointer to smart pointer:
MyClass* pMyClass = new MyClass;
boost::shared_ptr<MyClass> pSmartMyClass;
pSmartMyClass.reset(pMyClass);
or simply
pSmartMyClass.reset(new MyClass);
Smart pointer to plain pointer:
boost::shared_ptr<MyClass> pSmartMyClass(new MyClass);
MyClass* pMyClass = 0;
pMyClass = pSmartMyClass.get();
Never use get() and reset() methods when both are smart pointers.
boost::shared_ptr<MyClass> pSmartMyClass1;
boost::shared_ptr<MyClass> pSmartMyClass2;
pSmartMyClass1 = pSmartMyClass2; // right
pSmartMyClass1.reset(pSmartMyClass2); // wrong
pSmartMyClass1.reset(pSmartMyClass2.get()); // wrong
pSmartMyClass1 = pSmartMyClass2.get(); // wrong
10.1. If ... then ... else
Alternatively to the classical syntax, it's possible to use the following instead:
(condition) ? (cout << "true") : ("cout << "false")
This is normally used for short commands and is normally placed on a single line.
10.2. Switch statement
switch(myVariable)
{
case 1:
{
return true;
}
break;
case 2:
{
return true;
}
break;
default:
{
return false;
}
break;
}
11.1. Copying array of char to std::string
char myArray[] "Hello";
unsigned int myArrayLenght = 4;
std::string myString;
myString.assign(myArray, myArray + myArrayLenght);
11.2. Declaring a string and initializing it with more char[]
#define "One";
#define "Two";
std::string myString = "One" "Two";
12.1. Usage
A template provides the capability to define classes and methods without specifying the type of input/output.
Here an example:
This should be placed in the .cpp file:
template <typename MyType>
MyMethod(MyType myParameter)
{
// make something with myParameter
}
This should be placed in the .hpp file:
template<typename MyType>
clss Class
{
public:
void myMethod(MyType);
}
And here is an example about how to use it:
Class<in> intClass;
Class<string> stringClass;
intClass.myMethod(5);
stringClass.MyMethod("hello");
13.1. Copying a structure
If the structure doesn't contain pointers or references, it's possible to copy it with the operator =.
typedef struct MyStruct
{
int foo;
char bar;
}
MyStruct;
MyStruct a, b;
a.foo = 1;
a.bar = 2;
b = a;
In this case, the operator= is called for each member and struct a is copied one byte after the other to struct b.
Note:
MyStruct* pA, pB;
pA = pB;
In this case, only the pointers copied!
Danger: if the structure contains pointers or references, only the pointers will be copied and not the content where they point to.
Therefore, in this case, one solution is to use memcpy:
typedef struct MyStruct
{
int length;
char* value;
}
MyStruct;
MyStruct a, b;
char string[] = "Emi";
a.length = strlen(string);
a.value = new char[strlen(string)];
a.value = string;
b.length = a.length;
b.value = new char[b.length];
memcpy(b.value, a.value, a.length);
On other solution is to use std::copy:
std::copy(a.value, a.value + a.length, b.value);
Note: std::string needs the following line
#include<string>
13.2. Initializing a structure
This will initialize the structure with zeros:
memset(&myStruct, 0, sizeof(myStruct);
13.3. Setting, resetting and checking bit
Given:
FLAG = 0x0100
int bitmask = 0;
Set bit:
bitmask |= FLAG;
Reset bit:
bitmask &= ~FLAG;
Check bit:
if((bitmask & FLAG) == FLAG)
{
print "Bit is set\n";
}
else
{
print "Bit is not set\n";
}
14.1. Printing a vector
for(size_t i = 0; i < vector.size(); i++)
{
std::cout << vector[i] << std::endl;
}
14.2. Copying a vector
MyClass objectA, objectB;
std::vector<MyClass> v1, v2;
v1.push_back(objectA);
v1.push_back(objectB);
v1.insert(v1, v1.end(), v2.begin(), b2.end());
14.3. Shifting a vector
To shift left:
std::vector<char>::iterator b = input.begin();
std::advance(b, shiftNbytes);
input.erase(input.begin(), b);
|