Archive for July, 2007

A word on virtual functions

Monday, July 16th, 2007

Once more, I’ll write a few words on virtual functions, as they are often confusing for myself. In C++ they exhibit an interesting behavior (by definition!) when casting from one class to another, that can be confusing if one isn’t very fond of the properties of a virtual function. In particular, in C++, virtual functions inside objects behave as being of the type they have been instantiated as, not as the types they may be converted to (by casting) throughout your code.

Take the following example:

#include <iostream>
 
using namespace std;
 
class A {
   public:
       virtual void Run() {
            cout << "A::Run" << endl;
       }
       void Yoke() {
            cout << "A::Yoke" << endl;
       }
};
 
class B : private A {
    public:
        virtual void Run() {
            cout << "B::Run" << endl;
        }
        void Yoke() {
            cout << "B::Yoke" << endl;
        }
};

Now, let us try to use classes A and B normally:

int main() {
    A* a = new A();
    B* b = new B();
 
    a->Run();
    b->Run();
 
    return 0;
}

As one would expect, the result is A::Run and B::Run, normally. Function “Run” from class B overloads function “Run” inside class A, hence this behavior. Now let’s see what happens when we cast from one class to another.

int main() {
    A* a = new A();
    B* b = ( B* )a;
 
    b->Run();
 
    return 0;
}

Calling the “Run” function, perhaps surprisingly, invokes the Run method of class A and outputs “A::Run()”. Although the type of variable b is a B*, in truth it is an instance of class A. What virtual functions are supposed to do is, lookup the real object type (meaning: the class with which they were instantiated), and call THAT function. The “b” variable was instantiated as A and hence this behavior.

This behavior is often desired. It is used when a parent class wants to call a function that can be overloaded; in that case, all the developer needs to do is instantiate the object using the child class. Take the following example, where this behavior helps:

class Foo {
    void Go() {
        cout << "Foo::Go" << endl;
        this->Run();
    }
    virtual void Run() {
        cout << "Running as Foo" << endl;
    }
}
 
class Bar : private Foo {
    void Run() {
        cout << "Running as Bar" << endl;
    }
}
 
int main() {
    Bar* bar = Bar();
 
    bar->Go();
}

While class Bar offers a generalized behavior in function Go, it allows specialization, if the derived class desires, by making its Run function virtual. Notice that the proper function is invoked because the instantiation is done as Bar, not as Foo, even though the Go function is defined within Foo.

Sometimes, however, this behavior is not desired. Take, for the sake of illustration, as an example, a base class which is instantiated by a library that is unaware of possible class extensions, and returned by one of its functions or passed as an argument to a user-defined callback function. Having that type of object, the user might desire to cast it to a different type, a derived class, which they could want to be specialized, by defining this special behavior in an overloaded function called by the parent.

In some cases, it is possible to solve this problem by simply making functions non-virtual. This allows the program to execute the functions based on variable types (casted or defined types), and not actual object types (instantiated type). Yet another way to do it is to define a constructor for the derived class that accepts the base class as an argument and instantiates accordingly. The latter method might not always be possible, however, depending on the context.

I hope this post made some things about virtual functions clearer :-)

Entering a child = Leaving parent?

Sunday, July 15th, 2007

At least this is what internet browsers think.. or ok, not exactly.

Let me explain:

If you have an element which has onmouseover and onmouseout events, and children inside it, if you enter one of the children, onmouseout of parent element will fire, then the onmouseover of the child, and then again the onmouseout of the parent.

Example:

<body>
     <div style="width: 500px; height: 500px; background-color: red;" 
     onmouseout="alert( 'leaving parent' );"  
     onmouseover="alert( 'entering parent' );" id="parent">
          <div style="width: 100px; height: 100px; background-color: blue;" 
         onmouseover="alert( 'entering child' );" 
         onmouseout="alert( 'leaving child' );" id="child">
          </div>
     </div>
</body>

If you enter the parent div, you will get an alert saying: “Entering parent” (obviously). But if you then enter the child-div,

you will get these alerts (consecutively):

“Leaving parent”, “Entering child”, “Entering parent”

The same thing happens if you then leave the child: you will get these alerts:

“Leaving child”, “Leaving parent”, “Entering parent”

Now, suppose that you have a <div> element,
which on mouse-over creates a <form> child and on mouse-out destroys it.

This won’t lead to the result you ‘d expect:

When you mouse-over it, it will create the <form>,
but instantly destroy it because you entered the child.

And then again, as you are not on the child,
you are re-entering the <div> and thus creating the <form> again.

…and so on.