basti@orthogo.UUCP (Sebastian Wangnick) (11/23/90)
I just recognized that my cfront 2.0 installs the vtable
of a derived class only *after* the constructor of the
base class is called.
This implies that you are not allowed to use virtual member
functions within the constructor of an abstract base class.
Here an example program that you can compile to see whether
other compilers do the same:
extern "C" void abort ();
extern "C" void printf (...);
typedef int Rect;
class Window
{
public:
Window (Window* parent = 0);
virtual Rect Size ();
virtual void ChildAdd (Rect size) {}
};
Window::Window (Window* parent)
{if (parent)
parent->ChildAdd(Size());
}
Rect Window::Size ()
{printf("SubclassResponsibility\n"); abort(); return 0;}
class NullWindow: public Window
{
public:
NullWindow (Window* parent = 0) : (parent) {}
virtual Rect Size () {return 0;}
};
void main ()
{Window* parent = new NullWindow;
Window* child = new NullWindow(parent);
}
What will happen if you compile this? Well, my cfront2.0-generated code
returns "SubclassResponsibility" because from within the constructor of
class Window the function Window::Size is called, not NullWindow::Size
as I expected!
Now: Is this a bug or a feature ??
Sebastian Wangnick (basti@orthogo.uucp)jbuck@galileo.berkeley.edu (Joe Buck) (11/27/90)
Not illegal, they just don't do what you think. In article <822@orthogo.UUCP>, basti@orthogo.UUCP (Sebastian Wangnick) writes: > I just recognized that my cfront 2.0 installs the vtable > of a derived class only *after* the constructor of the > base class is called. > This implies that you are not allowed to use virtual member > functions within the constructor of an abstract base class. This is documented in Ellis and Stroustrup's Annotated C++ Reference Manual, which the ANSI committee is using as the base document for the official standard. The standard actually says that if you do call a virtual method in the constructor, that the base class method is always called, even if you redefine the method. That is, if you have class Derived: public Base { ... } any virtual methods you call in the constructor for Derived act as though the object were of type Base. > Now: Is this a bug or a feature ?? It's a feature (and a required one at that). Any compiler that does what you want violates the standard. -- Joe Buck jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck
rpk@rice-chex.ai.mit.edu (Robert Krajewski) (11/27/90)
If the base class constructor could use a function designed to be used with a derived class instance, that (derived) function might try to refer to data members that weren't yet initialized. In a sense, an object ``evolves'' as more and more specialied constructors are run. The problem is that we would like the C++ constructor and destructor mechanism to handle *all* the semantics of creating and destroying and object, including tasks that must be invoked (using virtual functions) on all members of base class from which other classes are expected to be derived. You can get around this calling separate functions for initialization and deletion, but such a technique is awkward for stack-allocated objects. ---- Robert P. Krajewski Internet: rpk@ai.mit.edu ; Lotus: robert_krajewski.lotus@crd.dnet.lotus.com
chip@tct.uucp (Chip Salzenberg) (11/30/90)
According to jbuck@galileo.berkeley.edu (Joe Buck): >[E&S] actually says that if you do call a virtual method in the >constructor, that the base class method is always called, even >if you redefine the method. This is true, but only if you are calling the virtual function from the actual constructor function body. If you call a virtual function from a constructor by other means, such as calling a function that calls the virtual function, E&S says that the behavior is undefined, i.e. all bets are off. -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip> "I've been cranky ever since my comp.unix.wizards was removed by that evil Chip Salzenberg." -- John F. Haugh II
jimad@microsoft.UUCP (Jim ADCOCK) (12/04/90)
In article <822@orthogo.UUCP> basti@orthogo.UUCP (Sebastian Wangnick) writes: |I just recognized that my cfront 2.0 installs the vtable |of a derived class only *after* the constructor of the |base class is called. | |This implies that you are not allowed to use virtual member |functions within the constructor of an abstract base class. .... |Now: Is this a bug or a feature ?? This is a "feature" -- IE this is how the C++ language is defined. While in the base class constructor your object is only a base object, it does not become a derived object until the derived constructor begins to work on it. Compilers may rely on this language definition to play with the nasty bits such as vtable and vbase pointers during construction. Thus, attempting to defeat this language "feature" will be problematic and non-portable at best. Likewise in destructors, while in the derived class destructor your object is a derived object, but afterwards when the base destructor is called your object has regressed to becoming just a base object again. These "features" allow base class constructors and destructors to be implemented in sensible ways despite what future class implementors might do in derived classes. Even the permission to use derived class virtual functions in the derived class constructor could be viewed as problematic, since your derived class object does not fully become such until the end of the derived class constructor. However, it was assumed that derived class writers could reasonably be held responsible for their own actions in using their own virtual functions within their own constructors. But beware: deamons lurk in wait for those who so use virtual functions! [In my opinion, one is best not to do substantive work inside a constructor in the first place. Constructors are best used to do things to place an object into the simplest mode where that object can meet its class invariants. Do your substative work, such as virtual function calls, after the constructors [standard disclaimer]]
pal@xanadu.wpd.sgi.com (Anil Pal) (12/05/90)
In article <27556AD1.350C@tct.uucp>, chip@tct.uucp (Chip Salzenberg) writes: [ Referring to constructor calling base class virtual function] |> This is true, but only if you are calling the virtual function from |> the actual constructor function body. If you call a virtual function |> from a constructor by other means, such as calling a function that |> calls the virtual function, E&S says that the behavior is undefined, |> i.e. all bets are off. Are you sure about this? My copy of E&S says (page 294, sec. 12.7) Member functions may be called in constructors and destructors. This implies that virtual functions may be called (DIRECTLY OR INDIRECTLY [emphasis mine]). The function called will be the one defined in the constructor's (or destructor's) own class or its bases, but *not* any function overriding it in a derived class. [...] The effect of calling a PURE [emphasis mine] virtual function directly or indirectly [...] is undefined. If what you say is in fact stated somewhere else in E&S, then there is a definite contradiction. -- Anil A. Pal, Silicon Graphics, Inc. pal@sgi.com (415)-335-7279
chip@tct.uucp (Chip Salzenberg) (12/08/90)
A long time ago, someone (okay, it was me) wrote: > If you call a virtual function from a constructor [indirectly], > E&S says that the behavior is undefined, i.e. all bets are off. In response, pal@sgi.com quoted E&S page 294, section 12.7: > Member functions may be called in constructors and destructors. > This implies that virtual functions may be called (DIRECTLY OR > INDIRECTLY [emphasis mine]). The function called will be the one > defined in the constructor's (or destructor's) own class or its > bases, but *not* any function overriding it in a derived class. > [...] > > The effect of calling a PURE [emphasis mine] virtual function > directly or indirectly [...] is undefined. Mea culpa, mea culpa, mea maxima culpa. Pal's quotation is correct, I was wrong, the truth is known, and the world is a better place. -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip> "I'm really sorry I feel this need to insult some people..." -- John F. Haugh II (He thinks HE'S sorry?)
pkt@lpi.liant.com (Scott Turner) (12/08/90)
In article <27556AD1.350C@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes: >This is true, but only if you are calling the virtual function from >the actual constructor function body. If you call a virtual function >from a constructor by other means, such as calling a function that >calls the virtual function, E&S says that the behavior is undefined, >i.e. all bets are off. Actually, p. 294 of E&S says that virtual functions can be called from constructors "directly or indirectly". What Chip may have in mind is that a call to a _pure_ virtual function from a constructor is in general undefined. -- Prescott K. Turner, Jr. Language Processors, Inc. 959 Concord St., Framingham, MA 01701 USA (508) 626-0006 UUCP: uunet!lpi!pkt Internet: pkt@lpi.liant.com