Saturday, June 30, 2007

The fall of MS fan

For most of life, I have been a Microsoft user. I wasn't a MS' fan. But I didn't find it not so bad working on Window, and it was fair enough for me, although it is not perfect.

I had great passion to try the Vista out, the long delayed version, 6 years or sthg. We all read abt it for many years, and how much it will be sthg fascinating and a new..bla..bla..bla
When I tried it on my PC, i was expecting sthg that could dazzle me.

finally, I got Vista business. I was totally wrong, I regret the day i installed Vista.

well, it is beautiful, the 3-D desktop switcher looks nice.
I faced many problems with Drivers. the problem is not that they r not verified by Vista. the problem that from time to time, I had to redefine the drivers.
my network card kept to be disconnected. I couldn't stay online for couple of hours. the stupid thing that when it disconnects, i have to press by myself "diagnose and repair" then should press "get a new IP" to ask the Vista to get another IP. What is this stupidity!!! didn't I define that already in the connection properties!! the answer to that question is the "ALLOW" :))
If u run sthg on vista, and precipitate away from ur PC, don't expect it is working.

u should wait because u will have to answer "Continue with getting a new IP?", "continue with opening this executable file"..etc I really hate this stupid thg in vista. i don't think i have to press 3 clickes just to run exe file..

The gadgets are terrible, I have never turned them on. they are not innovative and poor.

fighting to have a network connection really annoyed me.
this Vista eats the processor and the Memory. it slows down ur PC. without any tasks running ur RAM usage can be 512 MB. to use a PC now, u have to add $X to buy extra RAM for the Vista and $Y extra to more powerful processor, don't forget that u will pay for the Vista too :)
Vista price is too high. despite the license price is the almost the same since many old versions of windows, it is too high comparing with HW costs these days. Windows license can exceed 20% of ur costs!!!!

the only thg that may keep windows alive is that majority of mobile tools need windows to sync, and some softwares are not still available for MACs.

anyway, I didn't like the Vista thg.
Not friendly, no performance, no stability...nothing.

Thursday, June 28, 2007

Improve your Company using Workflow System

Work flow,
Business Process Management,
Business Process Modeling,
Methodologies,
Work Procedures

All these related words can come together to build an understandable vision of the workflow system.

The Business Process is a group of logically related tasks that come together to form a methodology to implement work procedures.
So companies try to automate these procedures using a workflow system to gain its benefits.

You can find more about workflow here.

So why do we need workflow system?
Some of the benefits we can get by using workflow can be briefed by the following

  • Improved efficiency - automation of many business processes results in the elimination of many unnecessary steps
  • Better process control - improved management of business processes achieved through standardizing working methods and the availability of audit trails
  • Improved customer service – consistency in the processes leads to greater predictability in levels of response to customers
  • Flexibility – software control over processes enables their re-design in line with changing business needs
  • Business process improvement - focus on business processes leads to their streamlining and simplification

How to implement a workflow system for our company?

Well, Thanks god we didn't have to pay for a license to build a system using Microsoft workflow foundation.

We have JBPM (Java Business process management) which is a flexible, extensible workflow management system build on Java and it is an Open source project.

A lot of open source projects are developed like (Open Business Engine The Open for Business Workflow Engine OpenWFE WfMOpen XFlow Micro-Flow JFlower YAWL Zebra Apache Agila Antflow Beexee Dalma Swish etc...)

I believe that RunaWFE is one of the best.

RUNA WFE is an environment for JBoss jBPM workflow engine.
It is a cross-platform end user solution for business process development and execution.

Together RUNA WFE and JBoss jBPM provide an easy to use business process management system.

RUNA WFE provides:

  • an end user GUI to define business processes without any coding: draw flowcharts, define roles and variables, lay out forms
  • an end user GUI to load and execute processes
  • an administrative interface to create and remove users/groups and grant rights
  • a possibility of writing automatic "bots" that can participate in business processes
  • a possibility to code new GUI elements, variable types, organizational structure functions etc. that extend existing RUNA WFE components and will be available to end users through the GUI

Then How to integrate our workflow system with other software?

Integrating RunaWFE with MySQL Database:

Simply, do the following steps:

  1. Add The File mysqldb-ds.xml to your jboss deploy folder "server\default\deploy".
  1. In server\default\conf\hibernate.cfg.xml Change

connection.datasource = java:/MYSQLDS
Dialect = net.sf.hibernate.dialect.MySQLDialect

  1. Important Note : Don't forget to add "com.mysql.jdbc.Driver" to your library This is done by adding "mysql-connector-java-3.1.14.jar" to the lib Folder.

Integrating RunaWFE with LDAP:

Unfortunately integrating RunaWFE with LDAP can be done to a certain level,

In any workflow system you have to define your users, their groups and also their permissions and Roles.

So you can authenticate through LDAP but you still has to add your ldap users in your workflow system so you can define their groups and Roles.

So what we will do now is to authenticate using our LDAP and also import our LDAP users into RunaWFE to manage their groups, Permissions and Roles.

Fortunately RunaWFE helps us in doing both the importing and the authentication.

To Add LDAP Authentication To RunaWFE Do the Following:

  1. Add the LDAPPasswordLoginModule to src\af\logic\ru\runa\af\authentication
public boolean login() throws LoginException {  

SERVER_URL= LDAPImporterResources.getServerURL();

if (callbackHandler == null)

throw new LoginException("No CallbackHandler provided.");

Callback[] callbacks = new Callback[2];

callbacks[0] = new NameCallback("actor name: ");

callbacks[1] = new PasswordCallback("password: ", false);

ExecutorDAO executorDAO = null;

try {

callbackHandler.handle(callbacks);

String actorName = ((NameCallback) callbacks[0]).getName();

if (actorName == null)

throw new LoginException("No actor name was provided.");

char[] tmpPasswordChars = ((PasswordCallback) callbacks[1]).getPassword();

if ((tmpPasswordChars == null) || (tmpPasswordChars.length == 0))

throw new LoginException("No password was provided.");

String password = new String(tmpPasswordChars);

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.ldap.LdapCtxFactory");

env.put(Context.PROVIDER_URL, SERVER_URL);

env.put(Context.SECURITY_AUTHENTICATION, "simple");

env.put(Context.SECURITY_PRINCIPAL, "uid="+ actorName +

",ou=people,"+ LDAPImporterResources.getDC());

env.put(Context.SECURITY_CREDENTIALS, password);

DirContext ctx = new InitialDirContext(env);

ctx.close();

executorDAO = DAOFactory.getInstance().createExecutorDAO();

actor = executorDAO.getActorCaseInsensitive(actorName);

succeeded = true;

return succeeded;

} catch (IOException e) {

throw new LoginException(e.toString());

} catch (UnsupportedCallbackException e) {

throw new LoginException(e.getMessage());

} catch (NamingException e) {

throw new LoginException(e.getMessage());

} catch (InternalApplicationException e) {

throw new LoginException(e.getMessage());

} catch (ExecutorOutOfDateException e) {

throw new LoginException(e.getMessage());

} catch (RuntimeException e) {

throw new LoginException(e.getMessage());

} finally {

try {

DAOHelper.close(executorDAO, true);

} catch (InternalApplicationException e) {

throw new LoginException(e.getMessage());

}

}

}

  1. Modify the LDAP importer Configuration File ldap-importer.properties in server/conf to point to your LDAP server.
  2. Change login-module.properties in server/conf to the LDAPPasswordLoginModule.

#ru.runa.af.authenticaion.NTLMLoginModule=SUFFICIENT
#ru.runa.af.authenticaion.InternalDBPasswordLoginModule=SUFFICIENT
#ru.runa.af.authenticaion.ADPasswordLoginModule=SUFFICIENT
#ru.runa.af.authenticaion.KerberosLoginModule=SUFFICIENT
ru.runa.af.authenticaion.LDAPPasswordLoginModule
=SUFFICIENT

  1. You have to modify some constant variable in class LDAPImporter to accommodate with your LDAP settings.
private static final String OBJECT_CLASS_ATTR_USER_VALUE = "user";
private static final String DISPLAY_NAME = "name";
  1. Run the LDAP importer Tool which will import your users to the ldap users group in the Executors list of Runa.
  2. If you changed the Administrator login password don't forget to change it in the LDAPimporter script.

Finally to create your own processes you can use the Graphical Process Designer which helps design your processes in a very simple way.

Enjoy your Automated Workflow System and your process improvement.

Java vs. C++ - Part One

These are only some of the differences between Java and C++ that I found so far that drew my attention and I think are worth mentioning.

JavaC++
Compiling source codeWhen we compile a source file a .class file is generated in java byte-codes ( machine independent = portability ) that is not translated into machine language instructions until in the run time when interpreted by the Java Virtual Machine
( machine dependent ).
A source file is compiled and linked to produce an .exe file in machine language that is ready to be executed when the file is loaded into memory and run by the operating system.
Function definitions All function definitions and variable declarations are inside Classes even main(). Nothing is allowed to be outside a class except imports and package names.Function definitions are outside class definitions. They have prototypes whose place decides function scope
Including classesImporting a package.* just directs the compiler to the location of classes used in the code so that only these classes are included not the whole package. while in C++ I think that including a header file means that all classes in that header file will be compiled and linked to the source file.
Ending class definitionsClass definitions end with } without a semicolon.Class definitions end with };
Creating objectsAll objects must be created with new, so they are all dynamically allocated in the heap.
Only primitive data types can be allocated on the stack.
Objects can also be created and allocated without new so they are put on the stack in the scope of their declaration.
Declaring a reference:Declaring a reference to an object without using new to allocate the object only reserves space for the reference and no object is created in memory until new is used and the resulting object is given to the reference to point to it.Declaring an object without initializing it makes the compiler call the default constructor for the object's class and memory is allocated for the object in the stack.
Calling static methodsClassName.methodName( args.. );ClassName::functionName( args.. );
or ObjectName.functionName( args..);
Wrapper classesJava has wrapper classes for primitive data types that contains static methods for handling them
e.g. String string = Integer.toString( intVariable );
C++ doesn't normally have them in its standard libraries
Array declaration and memory allocation:An array is considered an object that has to be allocated by new.
   int c[];

declares the array reference

   c = new int[ 12 ];

allocates the array and automatically initialize its elements to zero for numeric primitive types, false for boolean, null for references ( non-primitive types)
or

   int c[] = new int[ 12 ];
// in one step

you can never specify the number of elements in the [] in a declaration unlike C++.

For multiple array declarations:

   double a[], b[];        

a = new double[ 100 ];
b = new double[ 27 ];

or

double a[] = new double[ 100 ],
b[] = new double[ 27 ];
or
double[] a, b;

a = new double[ 100 ];
b = new double[ 27 ];

or

double[] a = new double[ 100 ],
b = new double[ 27 ];

Elements of an array of a primitive data type contain values of that data type.
While elements of an array of a non-primitive data type contian "references" to objects of that data type.

( they have the value null by default )

Allocating and initializing arrays in declarations:

   int n[] = { 32, 27, 64, 18, 95,
14, 90, 70, 60, 37 };
// initializer list

Array size is determined by the number of elements in the list. Here new operator is provided by the compiler and the array object is also dynamically allocated.

When a Java program is executed. the Java interpreter checks array element subscripts to be sure they are valid. If there is an invalid subscript, Java generates an exception: ArrayIndexOutOfBoundsException.

   int c[ 12 ];

declares and allocated memory for 12 int elements without initializing them also memory is not dynamically allocated but instead it is preserved from the start and is allocated in the stack I presume.
For multiple array declaration:

   double a[ 100 ],
b[ 27 ];

Elements of an array of any data type contain values or objects of that data type.
Objects for which an array can be declared must have a default constructor to be called for every element when the array is declared.

initializing arrays in declarations:

   int n[ 10 ] = { 0 };

initialize elements of array n to 0

   int n[] = { 1, 2, 3, 4, 5 };

array size determined by the number of elements in the list

No checking for array bounds is done by the compiler so the programmer must be very carful not to exceed the array length

Multiple subscripted arrays

Doesn't directly support multiple-subscripted arrays but allows the programmer to specify single-subscripted arrays whose elements are also single-subscripted arrays, achieving the same effect.
i.e. arrays of arrays:

   int b[][] = { { 1, 2 },
{ 3, 4, 5 } };

b[ 0 ] is a reference to an array of 2 elements
b[ 1 ] is a reference to an array of 3 elements

   int b[][];
b = new int[ 3 ][ 3 ];

3 by 3 array allocated

   int b[][];
b = new int[ 2 ][];

allocates rows

   b[ 0 ] = new int[ 5 ];

allocates columns for row 0

   b[ 1 ] = new int[ 3 ];

allocates columns for row 1

Directly supports multiple-subscripted arrays and their elements are placed consecutively in memory row after row and the elements are actually located by pointer arithmetic.

   int b[][] = { { 1, 2 },
{ 3, 4, 5 } };

causes an error in C++ "error: declaration of 'b' as multidimensional array must have bounds for all dimensions except the first."

   int b[][ 3 ] = { { 1, 2 },
{ 3, 4, 5 } };

declares and preserves memory for a 2 by 3 multidimensional array b and initializes missing element in the list b[ 0 ][ 2 ] by 0.

Passing arguments

Java does not allow the programmer to decide whether to pass an argument call-by-value or call-by-reference:
Primitive data type variables are always passed call-by-value.
Objects are not passed to methods; references to objects are passed
(call-by-value just like pointers in C++ are) so the method can manipulate the object directly.

You can pass primitive data types or objects either call-by-value or call-by-reference ( using pointers or references to them ).

Returns

When returning information from a method via a return statement:

Primitive data type variables are always returned by value (a copy is returned).
Objects are always returned by reference - a reference to the object is returned.

Objects and primitive data type variables can be returned by value or by reference

Constant variables

Constant variables ( read only variables ) are declared using final.

They are declared using const.

Tuesday, June 19, 2007

Erlang Vs Object Oriented

I think that in the future the functional programming community will be at peak. currently I think that the functional communities are too small to beat the Java community.

the functional is easier to any person. any one can write a functional code. Erlang for example has a light VM that can make profit of multiprocessors availability. this doesn't depend on certain compiler that enables parallelism in Java or C.
if you don't care about performance, think about parallelism as simpler way to structure software in a domain where there is a lot of natural concurrency.

I read a paper "Structured Programming Using Processes" in which the author tried to prove that the Erlang was capable to support a personal accounting software application. Maybe you can take a look to it later.

also, I like to point to Yaws, Yaws is a HTTP high performance 1.1 webserver particularly well suited for dynamic-content webapplications. I ma really amazed by its performance.

well, but why Erlang is not widely used till now?
Well the world likes Java. the type safe language. Security in distributed Erlang is “all or nothing,” so when a node is authenticated to another, it can perform any operation.
process isolation is not complete, a process can flood another process with messages, or it can steal all the CPU cycles by entering into an infinite loop.

Friday, May 25, 2007

Using action+client caching to speed up your Rails application

Too many visitors are visiting your website and loads of dynamic data are being delivered to your clients?. Of those visitors, you have more people reading your site's content than people modifying it? meaning, you get lots more GET requests than POST, PUT or DELETE?

If the above questions are all answered with a YES, then, my friend, you are desperately in need of caching. Caching will help you lessen the load on your servers by doing two main things:
  1. It eliminates lengthy trips to the (slow by nature) database to fetch the dynamic data
  2. It frees precious CPU cycles needed in processing this data and preparing it for presentation.
I have faced the same situation with a project we are planning, we are bound to have much more GETS than any other HTTP command, and since we are building a Restful application we will have a one to one mapping between our web resources (urls) and our application models. The needs of our caching mechanism are the following:
  1. It needs to be fast
  2. It needs to be shared across multiple servers
  3. Authentication is required for some actions
  4. Page presentation changes (slightly) based on logged in user
  5. Most pages are shared and only a few are private for each user
We have two answer the following now, what caching technique and what cache store we will use?

The cache store part is easy, memcached seems like the most sensible choice as it achieves points 1 & 2 and is orthogonal to the other 3 requirements. So it is memcached for now.

Now, which caching technique?. Rails has several caching methods, the most famous of those is Page, Action and Fragment Caching. Greg Pollack has a great writeup on these here and here. Model caching is also an option, but it can get a bit too complicated, so I'm leaving it out for now, it can be implemented later though (layering your caches is usually a good idea)

Page caching is the fastest, but we will use the ability to authenticate (unless we do so via HTTP authentication, which I would love to, but sadly is not the case). This leaves us with action and fragment caching. Since the page contains slightly different presentation based on the logged in user (like a hello message and may be a localized datetime string) fragment caching would sound to be the better choice, no? Well, I would love to be able to use action caching after all, this way I can server whole pages without invoking the renderer at all and really avoid doing lots of string processing by Ruby.


There is a solution, if you'd just wake up and smell the coffee, we are in Web 2.0 and we should think in Web 2.0 age solutions for Web 2.0 problems. What if add little JavaScript to the page that dynamically displays the desired content based on user role. And if the content is really little, why not store it in a session cookie? Max Dunn implements a similar solution for his wiki here and thus the page is served the same with dom manipulation kicking in to do the simple mods for this specific user. Rendering of those is done on the client so no load on the server, and since the mods are really small, the client is not hurt either, and it gets to get the page much faster, it's a win win situation. Life can't be better!

No, It can!. In a content driven website, many people check a hot topic frequently, and many reread the same data they read before. In those cases, the server is sending those a cached page yes, but it is resending the same bits which the browser has in it's cache. This is a waste of bandwidth, and your mongrel will be waiting for the page transfer to finish before it can consume another request.

A better solution is to utilize client caching. Tell the browser to use the version in its cache if it is not invalidated. Just send the new data in a cookie and and let the page dynamically modify itself to adapt to the logged in user. Relying on session cookies for dynamic parts will prevent the browser from displaying stale data between two different session. But the page itself will not be fetched over the wire more than once, even for different users on the same computer.

I am using the Action Cache Plugin by Tom Fakes to add client caching capabilities to my Action Caches. Basically things go in the following manner:
  1. A GET request is encountered and is intercepted
  2. Caching headers are checked, if none exists then proceed
    else send (304 NOT MODIFIED)
  3. Action Cache is checked if it is not there then proceed
    else send the cached page (200 OK)
  4. Action processed and page content is rendered
  5. Page added to cache, with last-modified header information
  6. Response sent back to browser (200 OK + all headers)
So how to determine the impact of applying these to the application
  1. We need to know the percentage of GET requests, which can be cached as opposed to POST, PUT and DELETE ones
  2. Of those GET requests, how many are repeated?
  3. Of those repeated GET requests, how many originate from the same client?
Those numbers can tell us if our caching model works fine or not, this should be the topic of the next installment of this article

Happy caching

Thursday, May 24, 2007

Agile Process

My first reading about Agile was the Agile Manifesto. I think this was enough to get the whole picture of the agile philosophy.
I really don't recommend that you get a book to read about the agility; it will be a contradiction to read a book as long as the Agile methods emphasize working software as the primary measure of progress. It is better you spend the time understanding your working environment and maturity to apply the best process that can fit with it.
I lived a similar experience with eSpace when they were aiming to get a CMM certificate, CMMI or whatever they will call it after couple of years.
I think that finally the people here got the good decision by putting this plan away, and put their own standards, the standards best fitting with their teams and their environment. I doubt their was a need to some white collar guy to supervise our documents and our working styles to decide whether we fit to Mr XYZ standards or not. I also got the chance to meet some guys from another company having this certificate. What I found is that they modified their hierarchical structure just to accommodate the standard although their team wasn't capable at all to support this hierarchy.

Anyway, let's move to another point...
When we talk about the agile process we should identify very well any possible limitations before adopting it. It is very clear for me that it needs mature people, and this can be considered as one of the limitations.
Another factor that may limit the agile adoption is the "distributed software". Lately all our projects are distributed. Customers are from Europe, USA, Gulf. Developers are working remotely from different areas.
What are the challenges behind such distributed agile work???

The answer of this question can be summarized in knowing that agile methods mainly rely on informal processes to facilitate coordination while distributed software development typically relies on formal mechanisms.

Challenges in Agile Distributed Development
  1. Communication need vs. communication impedance: How can we achieve a balance in formality of communication in agile distributed environments?
  2. Fixed vs. evolving quality requirements: the Agile relies on ongoing negotiations between the developer and the customer while Distributed Development often relies on fixed, upfront commitments on quality requirements.
  3. People- vs. process-oriented control: We appreciate the people-orientation the most.
  4. Lack of cohesion: Generally speaking about the distributed environment, people may feel In distributed development, participants are less likely to perceive themselves as part of the same team when compared to co-located participants. the agile adds some more excitement to it :)

Practices
  1. Process Refactor: Continuous process adjustments instead of following strictly the agile practices. It is also recommended to document the requirements at different levels of formality.
  2. Knowledge Spreading: the team should share their knowledge regarding different domains(business, code, test cases..etc). Alot of tools were developed to reduce the overhead of knowledge-sharing activities. Code/process Repository is a must. the Wiki also is a very important way to share the How-Tos between members. I can't neglect the Bugzilla with its role in creating database to help teams report issues and assign priorities.
  3. Short Iterations: any iteration should not exceed 2 weeks. short iterations help to detect any misunderstandings for the project business and prevent any time waste.
  4. Start with well-understood functionalities: In order to create the best atmosphere for developers there should be a solid sand to start to be familiar with the processes, tools, and the application. this can be some kind different that the agile which advocates the development of features prioritized as critical by the customer.
  5. Improve Communication: Synchronized work hours are very important for the team. Also try to make the informal communication be done through formal channels. for example, let it through the emails so that it can be archived. In the distributed Projects it is recommended that the project leader/manager should be involved in the communication and the synchronization process than the Agile practice. finally, some daily mechanisms should be done to maintain minimal communication like morning online meeting.
  6. Building Trust: trust involves both the team and the customers.

References:
1. Ebert, C. and Neve, P.D. Surviving global software development. IEEE Software 18, 2 (Mar./Apr. 2001), 62–69.
2. Highsmith, J. and Cockburn, A. Agile software development: The business of innovation. IEEE Computer 34, 9 (Sept. 2001), 120–122.
3. Matloff, N. Offshoring: What can go wrong? IT Professional (July/Aug.2005), 39–45.

Wednesday, May 23, 2007

Virtual functions in C++


"In order to implement the concept of Polymorphism which is a corner-stone of OOP the C++ compiler has to find a way to make it possible."


Lets see how the story begins.

Derived classes inherit member functions of the base class but when some member functions are not exactly appropriate for the derived class they should provide their own version of these functions to override the immediate base class' functions and make their own objects happy. So if any of these functions is called for a derived object the compiler calls its class' version of that function.

This works quite fine when the types of objects are known at compile time so that the compiler knows which function to call for each particular object. The compiler knows where to find the copy of the function for each class and so the addresses used for these function calls are
settled at compile time. ( static binding )

Suppose that we have a lot of derived objects at different levels of the inheritance hierarchy that have a common base class and that they need to be instantiated at run time. Here the compiler does not know in advance what derived class objects to expect. These objects would be dynamically allocated and the code for handling these objects should be able to deal with all them.

It is perfectly legitimate to use base class pointers to point to these objects but that requires the compiler to handle them exactly the same way they would handle their base class objects. So they would call base class versions of member functions and none of the member functions specific for the derived class would be accessible.

To solve this problem
Virtual functions are used to allow dynamic binding.

"...It seems that our friend, the compiler of course, is very resourceful."


To support Polymorphism at runtime the compiler builds at compile time
virtual function tables ( vtables ). Each class with one or more virtual functions has a vtable that contains pointers to the appropriate virtual functions to be called for objects of that class. Each object of a class with virtual functions contains a pointer to the vtable for that class which is usually placed at the beginning of the object.

The compiler then generates code that will:

1. dereference the base class pointer to access the derived class object.
2. dereference its vtable pointer to access its class vtable.
3. add the appropriate offset to the vtable pointer to reach the desired function pointer.
4. dereference the function pointer to execute the appropriate function.

This allows dynamic binding as the call to a virtual function will be
routed at run time to the virtual function version appropriate for the class.

Impressive isn't it?

Well that made me try just for fun to write code that would do these steps instead of the compiler.

But as I did this another question evolved.

How does member functions get their "this" pointer ? ( pointer to the object the function is called for )

I know that the compiler should implicitly pass 'this' as an argument to the member function so that it can use it to access data of the object it is called for.

I used in my example a single virtual function that takes no arguments and returns void.
So at first I tried calling the destination virtual function with no arguments. The function was called already but the results showed it has used some false value for 'this' that pointed it somewhere other than the object and gave the wrong results.

So I tried calling the function and passing it the pointer to the object and it seemingly worked just fine.

Here's the code I tried...


#include <iostream>

using std::cout;
using std::endl;

class Parent {
public:
Parent( int = 0, int = 0 ); // default constructor
void setxy( int, int );
int getx() const { return x; }
int gety() const { return y; }
virtual void print();
private:
int x;
int y;
};

Parent::Parent( int a, int b )
{
setxy( a, b );
}

void Parent::setxy( int a, int b )
{
x = ( a >= 0 ? a : 0 );
y = ( b >= 0 ? b : 0 );
}

void Parent::print()
{
cout << " [ x: " << x << ", y: " << y << "] ";
}

class Child : public Parent {
public:
Child( int a = 0, int b = 0, int c = 0 , int d = 0 );
void setzt( int c, int d );
int getz() const { return z; }
int gett() const { return t; }
virtual void print();
private:
int z;
int t;
};

Child::Child( int a, int b, int c, int d )
: Parent( a, b )
{
setzt( c, d );
}

void Child::setzt( int c, int d )
{
z = ( c >= 0 ? c : 0 );
t = ( d >= 0 ? d : 0 );
}

void Child::print()
{
Parent::print();
cout << " [ z: " << z << ", t: " << t << "] ";
}

class GrandChild : public Child {
public:
GrandChild( int = 0, int = 0, int = 0, int = 0, int = 0);
void sete( int );
int gete() const { return e; }
virtual void print();
private:
int e;
};

GrandChild::GrandChild( int a, int b, int c, int d, int e )
: Child( a, b, c, d )
{
sete( e );
}

void GrandChild::sete( int num )
{
e = ( num >= 0 ? num : 0 );
}

void GrandChild::print()
{
Child::print();
cout << " [ e: " << e << " ]";
}

int main()
{
Parent parentObj( 7, 8 );
Child childObj( 56, 23, 6, 12 );
GrandChild grandchildObj( 4, 64, 34, 98, 39 );

// declare an array of pointers to Parent

Parent *parentPtr[ 3 ];

cout << "size of Parent = " << sizeof( Parent ) << " bytes\n";
cout << "size of Child = " << sizeof( Child ) << " bytes\n";
cout << "size of GrandChild = "
<< sizeof( GrandChild ) << " bytes\n";


parentPtr[ 0 ] = &parentObj; // direct assignment
parentPtr[ 1 ] = &childObj; // implicit casting
parentPtr[ 2 ] = &grandchildObj; // implicit casting

cout << "\nThe Derived objects accessed by"
" an array of pointers to Parent:\n\n";

for ( int i = 0; i < 3; i++ ) {
cout << "Object " << i + 1 << " : ";
cout << "\tvtable ptr (" << *( ( void ** ) parentPtr[ i ] ) << ")\n" ;
// vtable ptr at the beginning of the object

// initialize pointer to function

void (* funptr ) ( Parent * ) = NULL;

// assign to it pointer to function in vtable

funptr = *( *( ( void (*** ) ( Parent * ) ) parentPtr[ i ] ) );

cout << "\t\tpointer 1 in vtable is (" << ( void * ) funptr
<< ")\n\t\t( pointer to virtual function 1 'print()' )";

cout << "\n\n\t\tdata: ";

funptr( parentPtr[ i ] ); // call the 1st function in vtable
// and passing ( this ) to it
// without using parentPtr[ i ]->print();
cout << "\n" << endl;
}

return 0;
}


The output should look like this:


size of Parent = 12 bytes
size of Child = 20 bytes
size of GrandChild = 24 bytes

The Derived objects accessed by an array of pointers to Parent:

Object 1 : vtable ptr (0043FD90)
pointer 1 in vtable is (00401480)
( pointer to virtual function 1 'print()' )

data: [ x: 7, y: 8]

Object 2 : vtable ptr (0043FD80)
pointer 1 in vtable is (004015B8)
( pointer to virtual function 1 'print()' )

data: [ x: 56, y: 23] [ z: 6, t: 12]

Object 3 : vtable ptr (0043FD70)
pointer 1 in vtable is (004016E6)
( pointer to virtual function 1 'print()' )

data: [ x: 4, y: 64] [ z: 34, t: 98] [ e: 39 ]



In order to reach the function pointer to the desired function ( print() ) the parentPtr of the object which normally points to its beginning had to be casted to type pointer to pointer to pointer to function before it was dereferenced to give the vtabel pointer and then dereferenced again to give the first pointer to function in the vtable.

Polymorphism uses virtual functions in another interesting way. Virtual functions enables us to create special classes for which we never intend to instantiate any objects. These classes are called abstract classes and they only used to provide an appropriate base class that passes a common interface and/or implementation to their derived classes.

Abstract classes are not specific enough to define objects. Concrete classes on the other hand have the specifics needed to have a real object. To make a base class abstract it must have one or more pure virtual functions which are those having = 0 added at the end of its function prototype.

virtual void draw() const = 0;

These pure virtual functions should be all overridden in the derived classes for these to be concrete ones or else they would be abstract classes too.

Suppose we have a base class Hardware. We can never draw, print the production date or price unless we know the exact type of hardware we're talking about. So it looks that class Hardware could make a good example for an abstract base class.

Another example could be class Furniture and it might look something like this:


Class Furniture {
public:
...
virtual double getVolume() const = 0; // a pure virtual
function
virtual void draw() const = 0; // another one here
...
}

Here class Furniture definition contains only the interface and implementation to be inherited.
It even does not contain any data members.

That's it.
Hope you liked this article.

I will be happy to receive your comments.