Dissecting Code

Monday, July 19, 2010

Factory Patterns

1. The Parameterized factory:

#include <iostream>

class Shape
{
public:
virtual void Draw() = 0;
};

class Circle: public Shape
{
public:
void Draw(){ std::cout<<"Circle::Draw"; }
};

class Square: public Shape
{
public:
void Draw(){ std::cout<<"Sqaure::Draw"; }
};

enum ShapeType{ Shape_Circle, Shape_Square };

class Factory
{
public:
static Shape& CreateShape( ShapeType shapeType );
};

Shape& Factory::CreateShape( ShapeType type )
{
switch ( type )
{
case Shape_Circle: return *new Circle();
break;
case Shape_Square: return *new Square();
break;
default: break;
}
}

int main()
{
Shape& s=Factory::CreateShape( Shape_Circle );
s.Draw();
return 0;
}



Disadvantages: Adding a new type of shape will need changes in the Factory method.



Getting around by the use of templates, we have:



#include <iostream>

class Shape
{
public:
virtual void Draw() = 0;
};

class Circle: public Shape
{
public:
void Draw(){ std::cout<<"Circle::Draw"; }
};

class Square: public Shape
{
public:
void Draw(){ std::cout<<"Sqaure::Draw"; }
};

template <class T>
class Factory
{
public:
static Shape& CreateShape();
};

template <class T>
/*static*/ Shape& Factory<T>::CreateShape()
{
return *new T();
}

int main()
{
Shape& s=Factory<Circle>::CreateShape();
s.Draw();
return 0;
}




There we have a much more concise version using the power of templates.

Labels: , ,

Sunday, July 18, 2010

Virtual Functions

Consider the following:


#include <iostream>

using namespace std;

class A
{
public:
virtual void func1( int a ){ cout<<"A::func1"; }
virtual void func2( int i=20 ){ cout<<i; }
};

class B: public A
{
public:
void func1( float a ){ cout<<"B::func1"; }
void func2( int i=40 ){ cout<<i; }
};

int main(int argc, char* argv[])
{
A* pb=new B;
pb->func1(1);
pb->func2();
return 0;
}



Can you guess the output for the same?



pb->func1(1) => A::func1!! This is so, because, B::func1 hides( as a result of overloading) A::func1, rather then override it. And in C++, overload resolution is done on the static type, as it is done at compile time.


pb->func2() => 20!! This is so because, although B::func2 is called, the compiler picks up the default value from the base class. So, default values should be the same down the class hierarchy.


As an aside, the C++ standard states that built in conversions have more priority then user defined conversions.


Source: http://www.gotw.ca/gotw/005.htm

Labels: ,

Wednesday, July 14, 2010

C++ variable assignment

Consider the following:

class A
{
int a;
public:
A(){a=0;}
A(int b):a(b){}
A(const A& a1){ a=a1.a; }
A& operator=( const A& a1){ a=a1.a; return *this; }
};


1) A a; => Constructor is invoked

2) A b=a; => Copy constructor is invoked.

A c;
c=b; => Assignment operator is invoked.

A a=10; =>Constructor is invoked to create a temporary A object. Then a's copy constructor is invoked.

Source: Guru of the day 1

Labels: ,

Monday, July 12, 2010

Of constants and R and L values

 

RValue: A value that can appear on the right of an expression only
LValue: A value that can appear on the left of an expression. An LValue is converted to an RValue implicitly. The vice-versa does not hold.

An important point: only LValues can be bound to references to non-constants. A temporary object is a RValue.

Consider the following:

#include <iostream>

using namespace std;

class A
{
public:
~A(){ cout<<"A"; }
};

class B: public A
{
public:
~B(){ cout<<"B"; }
};

B factory()
{
B temp;
return temp;
}


int main()
{
const A& obj = factory();
return 0;
}



This is valid in standard C++, as the const used along with the reference forces the life of the temporary object to the end of the scope of the block rather than the scope of the expression (which is generally the case for temporaries). The const in necessary for performing the above magic. Note here, we have no need for a virtual destructor too!!



Source: http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Labels: ,

Wednesday, July 7, 2010

Restricting template types: Requiring member functions

It is desired that a class parametrized by, say a single type argument, T, only be instantiated by types that provide a particular function ( say void foo() )



// T must have void T::foo()


template <class T>
class RequireFoo
{
}

A petty solution:


template <class T>
class RequireFoo
{
public:
~RequireFoo(){ void (T::*fptr)() = &T::foo; }
};

The above solution will throw a compiler error if non foo having class is used as a parameter.

A much cooler solution: Move this check out to a template class


template <class T>
class CheckFoo
{
public:
CheckFoo(){ void (T::*fptr) = &T::foo; }
}

template< class T >
class RequireFoo: CheckFoo<T>
{
}

Here, the responsibility of checking for foo is checked in base class CheckFoo's constructor which is automatically called when RequireFoo is instantiated.
Ideas from: http://www.gotw.ca/publications/mxc++-item-4.htm

Complete Code:



#include <iostream>

class HasFoo
{
public:
void foo(){}
};

class NoFoo
{
};

template <class T>
class CheckFoo
{
public:
CheckFoo(){ void (T::*fptr)() = &T::foo; }
};

template <class T>
class RequireFoo: CheckFoo<T>
{
public:
};

int main()
{
RequireFoo< HasFoo > t;
return 0;
}


Labels: