C++ Function Pointers Simplified!

18 10 2009

Background information
Pointer is a variable which holds the address of another variable. Where, function pointer is again a variable which holds the address of a function.

If you think pointers are evil, then function pointers must be Satan for you. 🙂 Well, is there any easy way to create function pointers from function prototype? Indeed, there is. Its the “BAT” technique. Never heard about it before? No problem. Its invented by me just now. After watching BatMan series from cartoon network.

FunctionPointers


The “BAT” technique is this –

  1. Put Bracket or parenthesis around the function name.
  2. Add Asterisk or star in-front of function name.
  3. Now Typedef it to create a new datatype. Means change the function name to new datatype name and add typedef infront of it.
  4. Now you can use the new function pointer datatype like ordinary variables.

For instance, Assume we want to make a function pointer for function – DWORD MyFunction( int a, int b).

1) Bracket
DWORD (MyFunction)( int a, int b);

2) Asterisk
DWORD (*MyFunction)( int a, int b);

3) Typedef
typedef DWORD (*MyFunctionPtr)( int a, int b);

Ah! you have created a function pointer – MyFunctionPtr for function type – ‘DWORD MyFunction( int a, int b)’
Now you can use it like any other variable in your code. For instance, just see the following code snippet with real world usage of function pointers.

// Callback function for progress notification.
bool NotifyProgress( int Percentage )
{
 // Display progress and return true to continue.
 return true;
}

// typedef function pointer.
typedef bool (*NotifyProgressPtr)( int Percentage );

// DVD Burning function with pointer to NotifyProgress
// to update progress.
void BurnDVD( NotifyProgressPtr FnPtr )
{
 for( int Progress = 0; Progress <= 100; ++Progress )
 {
 // Call the function.
 (*FnPtr)(Progress);
 }
}

// Main function.
int _tmain(int argc, _TCHAR* argv[])
{
 // Ummm... Burn one DVD.
 BurnDVD( NotifyProgress );
 return 0;
}


Function pointers are not that much evil. Isn’t it? 😉


Targeted Audience – Beginners.





How to Delete Duplicate entries from STL containers?

16 04 2009


If you want to remove duplicate items, you can go for stl::set. But what to do if you want to delete duplicate data from other containers?

removeduplicate
Picture Courtesy – Squidoo


You can use std::unique() algorithm to remove adjacent duplicate items. So at first, sort your data, then call std::unique(). Now all the duplicate data will be rearranged to end of container. Now delete the unwanted range of duplicate data. Have a look at code snippet below.

#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
    // Election list.
    vector<string> ElectionList;
    ElectionList.push_back( "Sam" );
    ElectionList.push_back( "John" );
    ElectionList.push_back( "Ron" );
    ElectionList.push_back( "Sam" );
    ElectionList.push_back( "John" );

    // Sort the list to make same items be together.
    sort( ElectionList.begin(), ElectionList.end());

    // Rearrange unique items to front.
    vector<string>::iterator Itr = unique(
        ElectionList.begin(),
        ElectionList.end());

    // Delete the duplicate range.
    ElectionList.erase( Itr, ElectionList.end());
}


Take care that std::unique() just removes the adjacent duplicate entries. It wont remove the entire duplicate entries present in the container. That’s why we need to sort the container at first, which will arrange all duplicate entries to adjacent  locations. 😉


Targeted Audience – Beginners.





How to Pass Array by Reference?

15 03 2009


We used to use arrays, a lot. But did you ever tried how to pass array by reference to another function? Yes. Its a bit tricky.

arraybyreference


Receiving arrays by reference have special syntax. The arrayname and & symbol should be enclosed in parenthesis. And you should specify the size of array. Have a look at the following code snippet.

// Receive Array by reference.
void GetArray( int (&Array) [10] )
{
}

// Test array by reference.
void CRabbitDlgDlg::TestArray()
{
    // Pass array by reference.
    int Array[10] = { 0 };
    GetArray( Array );
}


Indeed, you can pass the array as pointer and then use it. But if you ever need to pass an array by reference, then remember this tip.


Targeted Audience – Beginners.





How to Assert on Object Slicing?

11 03 2009

What is Object Slicing?
If derived object is assigned to Base object, then the derived object will be sliced off and only the base part will be copied. Indeed it will cause abnormalities. But is there any mechanism, atleast to assert while object slicing?
objectslicing


You can do it by adding an overloaded constructor for derived in Base class and then assert in it. For instance,

// Forward Declaration.
class Derived;

// Base class.
class Base
{
public:
    // Default Constructor.
    Base() {}
    Base( Derived& derived ) { ASSERT( FALSE ); }
};

// Derived class.
class Derived
{
};
...

// Test code.
Base ObjBase;
Derived ObjDerived;

ObjBase = ObjDerived;


Take care that it won’t work for passing pointer and reference. But still good enough. nah?


Targeted Audiance – Intermediate.





How to Delete Pointers in Vector or Map in Single Line?

2 03 2009


If you have two or three STL containers which holds pointers in your class as members, then I’m sure that its destructor will be the worst readable one. For deallocating STL containers, we have to iterate through each container by for loop, then delete it. But is there any single line function call to delete all pointers in vector or map, just like chopping the top of a tray of eggs at once? 😉

deletestlcontainers
Picture Courtesy – elitalice.com


You can use for_each() and functors to achieve this. Check out the code snippet.

1) How to delete Vector of pointers in single line

// Necessary headers.
#include "functional"
#include "vector"
#include "algorithm"

using namespace std;

// Functor for deleting pointers in vector.
template<class T>
struct DeleteVectorFntor
{
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};

// Test Function.
void TestVectorDeletion()
{
    // Add 10 string to vector.
    vector<CString*> StringVector;
    for( int Index = 0; Index < 10; ++Index )
    {
        StringVector.push_back( new CString("Hello"));
    }

    // Now delete the vector in a single  line.
    for_each( StringVector.begin(),
              StringVector.end(),
              DeleteVectorFntor<CString*>());
}

1) How to delete Map of pointers in single line

// Necessary headers.
#include "functional"
#include "map"
#include "algorithm"

using namespace std;

// Functor for deleting pointers in map.
template<class A, class B>
struct DeleteMapFntor
{
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(pair<A,B> x) const
    {
        // Assuming the second item of map is to be
        // deleted. Change as you wish.
        delete x.second;
        return true;
    }
};

// Test function.
void TestMapDeletion()
{
    // Add 10 string to map.
    map<int,CString*> StringMap;
    for( int Idx = 0; Idx < 10; ++Idx )
    {
        StringMap[Idx] = new CString("Hello");
    }

    // Now delete the map in a single  line.
    for_each( StringMap.begin(),
              StringMap.end(),
              DeleteMapFntor<int,CString*>());
}


STL is really a powerful toolkit. Isn’t it?


Targeted Audience – Intermediate.





How to Remove Unreferenced Formal Parameter warning?

26 11 2008

Hands on legacy code base is a different kind of game! You have to learn a lot of tricks. During old days, legacy codebases have the compiler default settings. But now, for better error catching, most will switch  the warning level to high. Well, did you ever ported your legacy codebase by updating its project settings such as by switching the warning level from Level 3 (default) to Level 4, most probably you’ll get this – “Warning C4100: ‘Param2’ : unreferenced formal parameter”.

In most of the case, it might be some unused stack variable. But in some other cases, it might be the unused function parameters as well. For instance, if base class have some pure virtual function, we have to implement that, even if we don’t have any specific implementation for it. In that case, the parameters will not be used and can cause the same warning. Well how to “kick out” those warnings easily?

unreferrencedvariablewarning


Well, there are two tricks.

1) Use the macro – UNREFERENCED_PARAMETER
The common trick is to use the macro UNREFERENCED_PARAMETER(). When it expands, it just assigns the variable to itself. Just like a=a. Which will remove the warning, since the variable is used to assign to itself.

// The function that derived class was forced to implement,
// since its pure virtual function defined in base.
void CRabbitDialogDlg::Function( bool Param1, bool Param2 )
{
    // Here Param1 and Param2 are not used which will
    // trigger warning. Now they won't.
    UNREFERENCED_PARAMETER( Param1 );
    UNREFERENCED_PARAMETER( Param2 );
}

2) Comment out the variable names.
Even though UNREFERENCED_PARAMETER() serves the need, its not efficient. isn’t it? It assigns the variable to itself and thus avoids the warning. Well there is another easy method. Just comment out the variable name. Check the code snippet below.

// The function that derived class was forced to implement,
// since its pure virtual function defined in base.
void CRabbitDialogDlg::Function( bool /*Param1*/, bool /*Param2*/ )
{
    // Since the variable name doesn't exist, how compiler can
    // complain that variable is not used. ;)
}


In one of my projects, I was forced write an empty implementation for a pure virtual function in derived class. And my client needs zero compilation warning. At that time I really struggled to remove this warning. 😀 Now when i shared it with you, it feels good!


Targeted Audiance – Beginners.





How to Rename Namespace?

23 11 2008


Namspaces are introduced to have logical grouping of classes. But as the framework grows you could often find that the namespace length grows which make the usage more difficult.

renamenamespaces

For instance, one namespace i’ve encountered is like this –

namespace Company
{
    namespace Product
    {
        namespace Communication
        {
            namespace Event
            {
                class CEventEx
                {
                };
            };
        }
    };
};

How much I’ve to go inside to address a class? Well, in big frameworks this kind of deep hierarchy is unavoidable. But, its a fact that it causes trouble to developer who uses it. Well, is there any idea to avoid that?


Well, you can rename the namespace to much more smaller one! Have a look at the code snippet below.

// Rename the namespace
namespace ThirdPartyEvent = Company::Product::Communication::Event;
...
// Create the object by using renamed namespace.
ThirdPartyEvent::CEventEx objEvent;


There are still a lot of gems inside C++. isn’t it? 😉


Targeted Audience – Beginners.