How functions are resolved by compiler?
How it is determined whether the below call is bound at compile time or at runtime?
object.member_fn;//object is either base class or derived class object
p->member_fn;//p is either base class or d开发者_如何学JAVAerived class pointer
EDITED:
#include <iostream>
using namespace std;
class Base
{
public:
Base(){ cout<<"Constructor: Base"<<endl;}
~Base(){ cout<<"Destructor : Base"<<endl;}
};
class Derived: public Base
{
//Doing a lot of jobs by extending the functionality
public:
Derived(){ cout<<"Constructor: Derived"<<endl;}
~Derived(){ cout<<"Destructor : Derived"<<endl;}
};
void foo()
{
Base & Var = Derived();
Base*pVar = new Derived;
delete pVar;
}
void main()
{
foo();
std::cin.get();
}
out put:
Constructor: Base
Constructor: Derived
Constructor: Base
Constructor: Derived
Destructor : Base // the Derived is not called,
// the PVal is of type Base* and the fn is not virtual
//so compile time binding
Destructor : Derived
Destructor : Base
If the method is not virtual, both calls will be resolved at compile time. If the method is virtual then the first call in your question (obj.method()
) will be resolved at compile time for an object, but at runtime for a reference. The second call (objp->method()
) will be resolved at runtime. You can also force at compile time to call the non-derived version of a method.
struct base {
void f();
virtual void v();
};
struct derived : public base {
void f();
void v(); // intentionally left virtual out, it does not really matter
};
int main() {
derived d;
base & b = d;
base * bp = &d;
// compile time:
d.f(); // derived::f
d.v(); // derived::v
b.f(); // base::f -- non-virtual
bp->f(); // base::f -- non-virtual
// runtime:
b.v(); // derived::v
bp->v(); // derived::v
// compile time (user forced):
b.base::v(); // base::v
bp->base::v(); // base::v
}
In the first case, the type of object
is known at compile time (assuming it's not a reference). So this will be a static binding.
In the second case, a dynamic binding will be used, provided that the function is virtual
. Otherwise, a static binding.
I think it needs to be made clear that the constructor and destructor calls in the first case are made against an unnamed derive object these are NOT the constructor or destructor of Var. Var is just a reference type that doesn't require any special handling. As the compiler knows the type of this unnamed Derived object it correctly statically binds these to the derived class.
Similarly the constructor is statically bound in the second case because type following the new is derived. However when you call delete on the pointer of type base the compiler calls Base's destructor (again with static binding).
If you declared the base's destructor virtual then this final binding - that of which destructor to call when the delete happens would be dynamic and you would get identical output to that of the first case.
Dynamic binding is used only in case of pointer/reference and function called is virtual,
object.member_fn;//if object is not reference so static binding
object.member_fn;//if object is reference and member_fn is virtual dynamic binding
p->member_fn;//p is pointer and member_fn is virtual dynamic binding
Though there is one case where the reference bounds itself to a temporary will call the correct destructor.
#include <iostream>
using namespace std;
//virtual behavior with out the type being polymorphic
class Base
{
public: Base(){}
~Base(){}
};
class Derived:public Base
{
public:Derived(){}
~Derived(){
std::cout<<"Destructor is not virtual, but it is called";
}
};
void foo(){
Base & bound_to_temporary = Derived();
}
int main(){
foo();
cin.get();
}
Output: Destructor is not virtual, but it is called.
精彩评论