Re: Is this like calling a virtual function at construction time?
Sam wrote:
#include <iostream> // for std::cout
class IPure
{
public:
virtual void Work() = 0;
virtual ~IPure() {} // empty
};
class Base : public IPure
{
private:
IPure *next;
public:
Base() : next(this) {} // empty
void CallNextWork() { next->Work(); }
virtual void Work() { std::cout << "Base"; }
};
class Derived : public Base
{
public:
virtual void Work() { std::cout << "Derived"; }
};
int main()
{
Base *base = new Derived();
base->CallNextWork();
delete base;
return 0;
}
In the above code, I want Derived::Work to be called. And so it happens
with two compilers I've tested it.
But I wonder. Since Base::next is initialized at "Base"s
construction time, when its type is "Base", why is it that it works
the way I want?
The "real" type of "next" still points to a Derived object, even though
you created the pointer as a (Base *) and stored it as an (IPure *).
The memory allocated is for a whole Derived object, even though when you
store "next", the Derived portion hasn't been constructed yet.
Can I rely on this behavior? What does the C++ standard say about this?
From 9.3.2/1 (my emphasis):
"In the body of a nonstatic (9.3) member function, the keyword *this* is
a non-lvalue expression whose value is the address of the object for
which the function is called. ..."
This means that "this" points to the Base part of some object; this you
know already. But that address points to part of a partially-formed
Derived obect.
And from 5.2.2/1 (again, my emphasis):
"The function called in a member function call is normally selected
according to the static type of the object expression (clause 10), but
if that function is *virtual* and is not specified using a qualified-id
then the function actually called will be the final overrider (10.3) of
the selected function in the dynamic type of the object expression..."
This means that when all is said and done (that is, fully constructed),
"next" points to an object whose dynamic type is Derived, so
Derived::Work() is called when "next" is dereferenced in CallNextWork().
--
John Moeller
fishcorn@gmail.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]