Thread: dynamic/static binding

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    17

    dynamic/static binding

    hey, can you guys check this over for me and tell me if i got it right?

    Code:
    class Base
    {
    public:
    	virtual void f1()
    	{
    		f2(); // static binding, because f2 is static
    	}
    
    	void f2()
    	{
    		f3(); // dynamic binding because f3 is virtual
    	}
    
    	virtual void f3()
    	{
    	}
    
    	virtual ~Base() {}
    };
    is this correct? i followed the litmus test. but it never mentioned if it was a call to a method, only mentioned if it was a call to an object. its static. and dyanmic if its using a reference or pointer.
    Last edited by faze; 07-09-2005 at 07:27 PM.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    No. The call of f2() could be described as "static", but that's just because f2() is not virtual. The call to f3() involves dynamic binding, as the version of f3() called will be selected at run time, based on type of object.

    To expand;
    Code:
    class Base
    {
    public:
    	virtual void f1()
    	{
    		f2(); // static binding 
    	};
    
    	void f2()
    	{
    		f3(); // dynamic binding
    	};
    
    	virtual void f3()
    	{
    	};
    
    	virtual ~Base() {};
    };
    
    class Derived: public Base
    {
        public:
     
              void f3();
    };
    
    int main()
    {
          Base *x = new Base;
          Base *y = new Derived;
    
          x->f1();    // calls Base::f1() which calls Base::f2() which calls Base::f3();
          y->f1();    // calls Base::f1() which calls Base::f2() which calls Derived::f3()
          return;
    }
    The reason that Derived::f3() is called for y is that y is of type Derived, so the call to f3() within f2() resolves to Derived::f3().

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    17
    so what if i have the situation like this?

    Code:
    class Base
    {
    public:
    	virtual void f1()
    	{
    		f2(); // static binding
    	}
    
    	void f2()
    	{
    		f3(); // dynamic binding
    	}
    
    	virtual void f3()
    	{
    	}
    
    	virtual ~Base() {}
    };
    
    class Derived : public Base
    {
    public:
    	virtual void f1() 
    	{
    		f2(); // dynamic, because its calling its own f2()
    	}
    	virtual void f2() 
    	{
    		f3(); // dynamic, its calling its own f3()
    	}
    	virtual void f3()
    	{
    		Base::f3(); // dynamic, its calling Base's f3() which is virtual
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	Derived d;  // static 
    	Base& b1 = d;
    	Derived& d1 = d;
    
    	d.f1(); // static
    	d.f2(); // static
    	d.f3(); // static
    
    	d1.f1(); // dynamic
    	d1.f2(); // dynamic
    	d1.f3(); // dynamic
    
    	b1.f1(); // dynamic
    	b1.f2(); // static
    	b1.f3(); // dynamic
    in main:
    are you saying that since d is of type derived when b1 is assigned to d, it will use the Derived class, and not the base class? if yes, ignore the comments, cuz they are wrong.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Approximately yes ..... and your comments are wrong.

    Dynamic binding means that the function called is selected at run time, based on the type of the object. Static binding means it is fixed at compile time.

    Given a reference or a pointer to Base, dynamic binding will be used to resolve virtual member function calls if those functions are virtual in Base. Given an actual object of type Derived (as opposed to a pointer or reference to Derived) all the calls will be static.

    As Base::f2() is non-virtual, it is implicitly statically bound i.e. by not declaring it virtual, you tell the compiler that calling f2() for any object of type Base will always call Base::f2().

    When a function is called within a member function of Base, the call is implicitly made via the "this" pointer, so references to virtual members are dynamically bound.

    In your example, you have also encountered a feature known as the "hiding rule", because Base::f2() is non-virtual and Derived::f2() is virtual. Essentially the rule requires that Derived::f2() hides Base::f2(), and does not override it. i.e. unless you use the "Base::" notation, it is not possible to call Base::f2() for an object of type Derived.

    The following is your example, with comments corrected.
    Code:
    class Base
    {
    public:
    	virtual void f1()
    	{
    		f2(); // static binding (as f2() is non-virtual)
    	}
    
    	void f2()
    	{
    		f3(); // dynamic binding
    	}
    
    	virtual void f3()
    	{
    	}
    
    	virtual ~Base() {}
    };
    
    class Derived : public Base
    {
    public:
    	virtual void f1() 
    	{
    		f2(); // static as f2() is not virtual, and thanks to the "hiding rule" Derived::f2() hides Base::f2()
    	}
    	virtual void f2() 
    	{
    		f3(); // dynamic, as Base::f3() is virtual.  If Derived did not override it, Base::f3() would be called
    	}
    	virtual void f3()
    	{
    		Base::f3(); // static:  we're telling the compiler specifically to call Base::f3()
                                      //   if this was dynamic, this call would be infinitely recursive.
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	Derived d;  // static 
    	Base& b1 = d;
    	Derived& d1 = d;
    
    	d.f1(); // static
    	d.f2(); // static
    	d.f3(); // static
    
    	d1.f1(); // dynamic
    	d1.f2(); // dynamic.   If we have a Derived2, derived from Derived and that supplies an f2(), then Derived2::f2() will be called.
    	d1.f3(); // dynamic
    
    	b1.f1(); // dynamic
    	b1.f2(); // static, as Base::f2() is non-virtual
    	b1.f3(); // dynamic
    }

  5. #5
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    I sort of understand how you defined them as static or virtual calls now.
    - Derived::f1() is static because Base::f2() is static. However Derived::f2() hides that, so wouldnt that mean that Derived::f1() is going to call virtual Derived::f2() anyway, and should therefor be dynamic? I mean when its actually called Derived::f2() WILL hide Base::f2() so why is Derived::f1() considered static.
    - Also how is d.f2() static? Derived::f2() is calling virtual Derived::f3() (and we arent going to care what is called past that, reason at bottom) so should it not be dynamic?
    - And Derived::f3() is static because its calling virtual Base::f3().. which must be some rule that if you call Base explicitly its static, because otherwise I'd assume its dynamic.

    So shouldnt whether its a static or dynamic call be declared by what it actually calls, not what it 'would-of' called? For example, what it actually calls:

    Code:
    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    public:
    	virtual void f1()
    	{
            cout << "Base::f1() -> ";
    		f2(); // static binding (as f2() is non-virtual)
    	}
    
    	void f2()
    	{
            cout << "Base::f2() -> ";
    		f3(); // dynamic binding
    	}
    
    	virtual void f3()
    	{
            cout << "Base::f3() " << endl;
    	}
    
    	virtual ~Base() {}
    };
    
    class Derived : public Base
    {
    public:
    	virtual void f1() 
    	{
            cout << "Derived::f1() -> ";
    		f2(); // static as f2() is not virtual, and thanks to the "hiding rule" Derived::f2() hides Base::f2()
    	}
    	virtual void f2() 
    	{
            cout << "Derived::f2() -> ";
    		f3(); // dynamic, as Base::f3() is virtual.  If Derived did not override it, Base::f3() would be called
    	}
    	virtual void f3()
    	{
            cout << "Derived::f3() -> ";
    		Base::f3(); // static:  we're telling the compiler specifically to call Base::f3()
                        //   if this was dynamic, this call would be infinitely recursive.
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	Derived d;  // static 
    	Base& b1 = d;
    	Derived& d1 = d;
    
        cout << "Object 1, Function 1" << endl;
    	d.f1(); // static
        cout << "\n\nObject 1, Function 2" << endl;
    	d.f2(); // static
        cout << "\n\nObject 1, Function 3" << endl;
    	d.f3(); // static
    
        cout << "\n\nObject 2, Function 1" << endl;
    	d1.f1(); // dynamic
        cout << "\n\nObject 2, Function 2" << endl;
    	d1.f2(); // dynamic.   If we have a Derived2, derived from Derived and that supplies an f2(), then Derived2::f2() will be called.
        cout << "\n\nObject 2, Function 3" << endl;
    	d1.f3(); // dynamic
    	
        cout << "\n\nObject 3, Function 1" << endl;
    	b1.f1(); // dynamic
        cout << "\n\nObject 3, Function 2" << endl;
    	b1.f2(); // static, as Base::f2() is non-virtual
        cout << "\n\nObject 3, Function 3" << endl;
    	b1.f3(); // dynamic
    	
    	cin.get();
    }
    Output:
    Object 1, Function 1
    Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()

    Object 1, Function 2
    Derived::f2() -> Derived::f3() -> Base::f3()

    Object 1, Function 3
    Derived::f3() -> Base::f3()

    Object 2, Function 1
    Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()

    Object 2, Function 2
    Derived::f2() -> Derived::f3() -> Base::f3()

    Object 2, Function 3
    Derived::f3() -> Base::f3()

    Object 3, Function 1
    Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()

    Object 3, Function 2
    Base::f2() -> Derived::f3() -> Base::f3()

    Object 3, Function 3
    Derived::f3() -> Base::f3()
    Of course you cant decide if its virtual or static by what it ends up on, since it always will end up stopping on Base::f3(); in this example because it doesnt go anywhere, and therefor would make all of your calls static.

    I'm "eternally confuzzled (tm)" and could be wrong, and it wouldnt be the first time, considering I've only ready up on virtual declarations in classes once.
    Last edited by Dae; 07-10-2005 at 12:52 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The static type of object1 (the object named d in main()) is a Derived. The compiler is able to determine that, so does static binding when deciding which functions (f1(), f2(), and f3()) to call.

    You're mixing up the meaning of the word "static". Which happens a lot, as the word has several meanings in C++.

    We are talking, in this thread, about static versus dynamic binding. Dynamic binding is the mechanism by which a particular version of a virtual function executed, at runtime based on the type of an object. Static binding means that the function called is determined by the compiler, as the function to be called is independent of the runtime type of an object for which it is called.

    One type of static object is one that is declared using the "static" keyword. Another type of static object is an object that is declared outside any function (the keyword static is optional in this case). The concept of a static object is completely unrelated to the concepts of dynamic or static binding. A static object is one that, essentially, is not destroyed until the program exits. For example, the declaration "static SomeType x;" within a function means that the state of x will be saved between function calls;
    Code:
    #include <iostream>
    int y = 5;    // implicitly a static object
    
    void f()
    {
        static int x = 0;
        ++x;
        ++y;
       std::cout << x << ' ' << y << '\n';    
    }
    
    int main()
    {
        f();
        f();
    }
    will print out "1 6" and "2 7" (on separate lines).
    Last edited by grumpy; 07-10-2005 at 01:07 AM.

  7. #7
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Ohhh, "Dynamic binding is the mechanism by which a particular version of a virtual function executed, at runtime based on the type of an object. Static binding means that the function called is determined by the compiler," answers it (I wasnt refering static binding to the static keyword, but I was in the case of virtual). Though, while reading this I was thinking what the hell is the use of knowing if its static or dynamically binded then.. but then again I've not read up on this subject and will probably find out later (this is like asking whats the use of pointers and reading how later, I feel ashamed). I'll be moving on now....
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    17
    thanks for all the help guys, i think i understand it. this stuff is confusing
    Last edited by faze; 07-10-2005 at 07:18 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bjarne's member function binding sample is wrong?
    By George2 in forum C++ Programming
    Replies: 9
    Last Post: 03-11-2008, 04:05 AM
  2. boost::shared_ptr and dynamic binding
    By Mario F. in forum C++ Programming
    Replies: 2
    Last Post: 07-24-2006, 03:50 PM
  3. inet_aton()... Noob needs help with sockets :|
    By Maz in forum C++ Programming
    Replies: 3
    Last Post: 11-22-2005, 04:33 PM
  4. dynamic binding
    By freethenet in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-26-2004, 03:31 PM
  5. Static Binding & Dynamic Binding :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 12-31-2001, 08:51 PM