Skip to main content

C++ tips - I

Static members in .h and .cpp

  • A static variable in C++ when defined in a global function belongs to the file scope.
  • If a C++ static variable is defined as a member variable, regardless of how many objects we instantiate we only have one static variable across all of the instances. The static variable can be accessed via the instance or the class variable.
  • If a static variable is defined as member in a class declared in a .h file, the initialization should be done as [variable_type] ClassName::[variable_name] = [value]
  • A static function can only access static variables - makes sense huh??
  • A static function doesn't have the this pointer
  • class_name::static_function() - usage

Friend keyword


// A freind function
class A;
class B
{
private:
int i_Num;
public:
B(int iNum) { i_Num = iNum; }
friend void PrintNumbers(A &a, B &b); // non-member function, cannot use this
};
class A
{
private:
int i_Num;
public:
A(int iNum) { i_Num = iNum; }
friend void PrintNumbers(A &a, B &b);
};
void PrintNumbers(A &a, B &b)
{
std::cout << "A number is " << a.i_Num <<
" and the B number is " << b.i_Num << std::endl;
}
view raw freindFunc.cpp hosted with ❤ by GitHub
// A freind class
class B
{
private:
int i_Num;
public:
B(int iNum) { i_Num = iNum; }
friend class A;
};
class A {
private:
int i_Num;
public:
void PrintNumbers(B &b) {
std::cout << "A number is " << i_Num <<
" and the B number is " << b.i_Num << std::endl; // accessing the private member of B
}
}
view raw friendClass.cpp hosted with ❤ by GitHub
#include <iostream>
#include <ctime>
#include <sstream>
#include <fstream>
using namespace std;
// timestamp returns the current time as a string
std::string timestamp();
class LogStatement;
ostream& operator<<(ostream& ost, const LogStatement& ls);
class LogStatement {
public:
LogStatement(std::string s) : data(s), time_string(timestamp()) {
};
//This method handles all the outputs.
friend ostream& operator<<(ostream&, const LogStatement&);
private:
std::string data;
std::string time_string;
};
ostream& operator<<(ostream& ost, const LogStatement& ls) {
ost << "~|" << ls.time_string << '|' << ls.data << "|~";
return ost;
}
std::string timestamp() {
//Notice the use of a stringstream, yet another useful stream medium!
ostringstream stream;
time_t rawtime;
tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
stream << (timeinfo->tm_year) + 1900 << " " << timeinfo->tm_mon
<< " " << timeinfo->tm_mday << " " << timeinfo->tm_hour
<< " " << timeinfo->tm_min << " " << timeinfo->tm_sec;
// The str() function of output stringstreams return a std::string.
return stream.str();
}
/*
*
*/
int main(int argc, char** argv) {
char* testArr[3] = {"log 1", "log 2", "log 3"};
ostringstream log_data;
// This takes all the char arrays in the argv
// (except the filename) and produces a stream.
for (int i = 0; i < 3; i++) {
log_data << testArr[i] << ' ';
}
int iAnyNum=100;
log_data << iAnyNum;
LogStatement log_entry(log_data.str());
clog << log_entry << endl;
ofstream logfile("logfile", ios::app);
// check for errors opening the file
if (!logfile) {
return -1;
}
logfile << log_entry << endl;
logfile.close();
return 0;
}
view raw Logger.cpp hosted with ❤ by GitHub

Comments

Popular posts from this blog

Detaching a process from terminal - exec(), system(), setsid() and nohup

Linux processes are created by fork() and exec(). The very first process of POSIX systems is init and subsequent processes are derived from the init as parent. These subsequent processes are child processes. During forking the parent process copies itself - with all I/O, address space, stack, everything. The only thing that is different is the process ID. The parent and child will have 2 different process IDs. The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows: execl("/bin/sh", "sh", "-c", command, (char *) 0); system() returns after the command has been completed. system() executes a command specified in command by calling /bin/sh -c command , and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.  system() calls are often made within programs to execut...

C++ Callbacks using function pointers vs boost bind +boost function

In C, the most common uses of callbacks are as parameters to library functions like qsort , and as callbacks for Windows functions, etc. For example you might have a library that provides some sorting functions but you want to allow the library user to provide his own sorting function. Since the arguments and the return values do not change depending on the sorting algorithm, this can be facilitated in a convenient manner using function callbacks. Callbacks are also used as event listeners. onMouseClick(), onTerminalInput(), onData(), onConnectionStatus(), onRead() are probably some examples you've already seen in different libraries. The libraries have these callback functions and the users of the library are supposed to implement them. The library has a function pointer to these functions and calls them on their event loop which will invoke the code of the inherited classes of the library user. The implementation of function pointers is simple: they are just "code p...

sprintf, snprintf, strcpy, strncpy and sizeof operator

"C library functions such as strcpy (), strcat (), sprintf () and vsprintf () operate on null terminated strings and perform no bounds checking." "snprintf is safer than sprintf" What do these statements really mean? int sprintf ( char * str , const char * format , ... )  int snprintf ( char * s, size_t n, const char * format, ... );  char * strcpy ( char * destination, const char * source ); char * strncpy ( char * destination, const char * source, size_t num );   The usage is something like; char* msg1 = new char[10]; strcpy(msg1, "test"); // 1 char buffer[128]; sprintf(buffer, "%s", msg); //2 strcpy : Copies bytes until it finds a 0-byte in the source code. The string literal "test" has 4 characters and a terminating null character at end, therefore needs 5 characters at least on msg1.  Is this dangerous? Yes, because if the source message is not null terminated it will read until a null character ...