Funny you should have mentioned Delphi. Because it works exactly not the same way. So now I feel simply obligated to ask what do you think happens in abovementioned case?
Hm. It's been more than four years since I have had my last tech interview... OK, then :)
Given the fact that by the time of the destructor of a class A being called, whatever parts of the object defined in those classes derived from the class A have already been destroyed, it's hard for ~A() to call anything but whatever the VMT table of the class A points to. In other words, ~A() would call A::f() even if there was a B::f(), B was derived from A, the object being destructed belonged to the class B and f() was declared as a virtual function.
To complete the subject, I must mention the destructor might or might not be declared as a virtual one. If the "virtual" attribute was omitted, then
A* a; a = new B(); delete a;
would never call ~B().
It's hard to imagine it would've worked another way for any other classic object-oriented language. I haven't had any practice in Delphi for 6 or 7 years (I had stopped familiarizing myself with it soon after its second version was released), but I would be quite surprised to find out Delphi interpreted the OOP basics in a completely different way.
well, delphi's concept of constructors/destructors is (putting it mildly) different from c++. i am sleepy now so i won't delve into more details than just to say that delphi will call descendant's function. which does create problems and this is exactly why and how i know about it :-)
i guess you will be also surprised to know that delphi not only allows instantiation of abstract classes, but doesn't even give a shit warning about abstract protected method being not implemented in the descendant. which in my opinion completely defeats the purpose of abstract method.
Well, it proves my old decision not to bother with Delphi for the 101st time.
I was taking for granted any modern language would be smart enough to replace VMT pointers or do whatever else is required during the time of the object's creation or destruction to prevent the possibility of calling a function that potentially deals with those members which are yet to be created or have already been destroyed. Obviously, I was wrong :)
By the way, is it possible in Delphi to call its descendant's functions from a constructor of the parent class? If so, it makes no sense, either. Otherwise, it's inconsistent at very least.
As to the calling of abstract methods, C++ obviously doesn't allow doing that - however, I do experience a "pure virtual function call" message every time my SourceSafe client crashes. Don't ask me how Microsoft does that :) However, other than having the instruction pointer get to the pure virtual function definition as a result of an illegal workflow, I hardly think of any other possibility of calling it.
"pure virtual function call" has nothing to do with calling abstract methods, it just a NULL pointer dereferenced to a derived class with virtual methods.
It all depends on how effective the language needs to implement the polymorphism. Obviously, the VMT is more effective (although less flexible) than the reflection or any other RTTI-based/alternative mechanism.
As for the "nothing to do"... The "pure virtual function call" message is nothing more but the code of a stub all the non-implemented methods point to (or, as an alternative, a handler for the exception that is raised in case the instruction pointer has to proceed with the NULL address) - and this message is exactly what would pop up in case an abstract method was called.
(no subject)
Date: 2003-12-23 07:21 pm (UTC)(no subject)
Date: 2003-12-23 08:22 pm (UTC)Given the fact that by the time of the destructor of a class A being called, whatever parts of the object defined in those classes derived from the class A have already been destroyed, it's hard for ~A() to call anything but whatever the VMT table of the class A points to. In other words, ~A() would call A::f() even if there was a B::f(), B was derived from A, the object being destructed belonged to the class B and f() was declared as a virtual function.
To complete the subject, I must mention the destructor might or might not be declared as a virtual one. If the "virtual" attribute was omitted, then
A* a;
a = new B();
delete a;
would never call ~B().
It's hard to imagine it would've worked another way for any other classic object-oriented language. I haven't had any practice in Delphi for 6 or 7 years (I had stopped familiarizing myself with it soon after its second version was released), but I would be quite surprised to find out Delphi interpreted the OOP basics in a completely different way.
Comments?
(no subject)
Date: 2003-12-23 08:40 pm (UTC)well, delphi's concept of constructors/destructors is (putting it mildly) different from c++. i am sleepy now so i won't delve into more details than just to say that delphi will call descendant's function. which does create problems and this is exactly why and how i know about it :-)
i guess you will be also surprised to know that delphi not only allows instantiation of abstract classes, but doesn't even give a
shitwarning about abstract protected method being not implemented in the descendant. which in my opinion completely defeats the purpose of abstract method.(no subject)
Date: 2003-12-24 08:10 am (UTC)I was taking for granted any modern language would be smart enough to replace VMT pointers or do whatever else is required during the time of the object's creation or destruction to prevent the possibility of calling a function that potentially deals with those members which are yet to be created or have already been destroyed. Obviously, I was wrong :)
By the way, is it possible in Delphi to call its descendant's functions from a constructor of the parent class? If so, it makes no sense, either. Otherwise, it's inconsistent at very least.
As to the calling of abstract methods, C++ obviously doesn't allow doing that - however, I do experience a "pure virtual function call" message every time my SourceSafe client crashes. Don't ask me how Microsoft does that :) However, other than having the instruction pointer get to the pure virtual function definition as a result of an illegal workflow, I hardly think of any other possibility of calling it.
(no subject)
Date: 2003-12-24 10:30 am (UTC)"pure virtual function call" has nothing to do with calling abstract methods, it just a NULL pointer dereferenced to a derived class with virtual methods.
(no subject)
Date: 2003-12-24 11:24 am (UTC)As for the "nothing to do"... The "pure virtual function call" message is nothing more but the code of a stub all the non-implemented methods point to (or, as an alternative, a handler for the exception that is raised in case the instruction pointer has to proceed with the NULL address) - and this message is exactly what would pop up in case an abstract method was called.