soiffer@tekcrl.CRL.TEK.COM (Neil Soiffer) (01/09/89)
I could find nothing in "the book" or subsequent papers on whether constructors are inherited by a derived type. Normal functions are inherited, but in order for a constructor to be inherited, the compiler needs to recognize that the name of the constructor has changed to be the name of the derived class. All of the arguments that apply to why it is (sometimes) useful to inherit a normal function apply to why it is (sometimes) useful to inherit a constructor. In particular, when the derived type merely (re)defines some virtual functions, it is annoying (and error prone) to have to define constructors for the derived type that are identical to the base type's constructors. Because I could find nothing concerning the legality of inheriting constructors, I tried some examples with cfront 1.2.1 and g++ (v 1.27?). [Can you guess what the answer is -- you are almost certainly wrong :-)] Below are four very simple types: B and D (derived from B) have a single function "f" defined along with the constructor. VirtualB and VirtualD (derived from VirtualB) differ from B and D in that their single function "vf" is a virtual function. The main program tries to construct objects of type D, D*, virtualD, and virtualD*. Another behavior is demonstrated by a class hierarchy similar to "Virtual{B,D}" called Other{B,D,DD}. This hierarchy adds a third class adds a constructor to OtherD and a third class OtherDD that is derived from OtherD. Cfront allows the objects of type D and D*, but complains about constructors for virtualD and virtualD*. I believe that I had one example where cfront would allow a virtualD* but not a virtualD, but I can't seem to reconstruct that example anymore. In the "Other" example, cfront complains about the class definition of OtherDD "struct OtherDD needs a constructor". It also gives the error message argument 1 of type char * expected for OtherD::OtherD() g++ complains about the constructors for all of the objects, although the error messages differ for the malloc'd types: test.c:51: type `VirtualD' must have constructor to take parameter list test.c:54: structure has no method named `VirtualD' test.c:57: type `D' must have constructor to take parameter list test.c:60: structure has no method named `D' g++ does not complain about the "Other" example. I strongly feel that constructors should be inherited. Is this question answered anywhere? Is there a good reason why they shouldn't be inherited? What does cfront 2.0 do? Below is the test program: ----------------------------------------------- #include <stdio.h> class B { public: B(int n=5) {i=n;}; void f() {printf("f of B\n");}; protected: int i; }; class D: public B { public: void f() {printf("f of D\n");}; }; class VirtualB { public: VirtualB(int n=5) {i=n;}; virtual void vf() {printf("vf of VirtualB\n");}; protected: int i; }; class VirtualD: public VirtualB { public: virtual void vf() {printf("vf of VirtualD\n");}; }; class OtherB { public: OtherB(int n=5) {i=n;}; virtual void vf() {printf("vf of OtherB\n");}; protected: int i; }; class OtherD: public OtherB { public: OtherD(char *s) {i = atoi(s);}; // this is the difference from Virtual above virtual void vf() {printf("vf of OtherD\n");}; }; class OtherDD: public OtherD { public: virtual void vf() {printf("vf of OtherDD\n");}; }; main() { VirtualD *vd_obj_ptr = new VirtualD(3); vd_obj_ptr->vf(); VirtualD vd_obj = VirtualD(3); vd_obj.vf(); D *d_obj_ptr = new D(3); d_obj_ptr->f(); D d_obj = D(3); d_obj.f(); }
mat@mole-end.UUCP (Mark A Terribile) (01/10/89)
> I could find nothing in "the book" or subsequent papers on whether > constructors are inherited by a derived type. Normal functions are > inherited, but in order for a constructor to be inherited, the compiler > needs to recognize that the name of the constructor has changed to be > the name of the derived class. ... Constructors are not inherited. ``Of course'' the base class's constructors *are* called (See B. Stroustrup's book, section 7.2.6) and there is nothing to prevent you from making the derived constructor(s) inline. > ... In particular, when the > derived type merely (re)defines some virtual functions, it is annoying > (and error prone) to have to define constructors for the derived type that > are identical to the base type's constructors. If the constructors are inline and written inline, it's no longer so error prone. > I strongly feel that constructors should be inherited. Is this question > answered anywhere? Is there a good reason why they shouldn't be inherited? I disagree, mostly because the five or six thousand lines of C++ that I've written (not a lot, I realize) have not shown me any real need and because this sounds like it could be a door thrown open to errors of omission in large classes of problems. If you find it necessary, you might want to look for another way to express the type relationships that you have. With a little more experience, I might be able to write some concrete examples; right now I cannot. -- (This man's opinions are his own.) From mole-end Mark Terribile
soiffer@tekcrl.CRL.TEK.COM (Neil Soiffer) (01/17/89)
I have received a few replies to my question about whether constructors are inherited. Most people said no (but seemed to ignore the program that I included that showed that in cfront, they are occasionally inherited). I have found another case where both g++ and cfront agree that the constructors are inherited. This case raises some questions about c++ consistency. In a nutshell, if B is a base class with a constructor "B(int)" D is derived from B and does not declare any new constructors, then D d(5) is allowed, but D d = d(5) is not allowed. [actually, if B has a virtual function defined on it, then cfront doesn't allow either form and complains about the class definition of D lacking a constructor] Unfortunately, the abbreviated form can not be used with "new" for heap-allocated storage, so it sufficient for my purposes. In Stroustrup's book, the only comment on the first form "D d(5)" that I could find is on page 139, saying that the first form is an abbreviation of the second form. Why should an abbreviation behave differently than the full form? In my original message, I claimed that: > all of the arguments that apply to why > it is (sometimes) useful to inherit a normal function apply to why it > is (sometimes) useful to inherit a constructor. In particular, when the > derived type merely (re)defines some virtual functions, it is annoying > (and error prone) to have to define constructors for the derived type that > are identical to the base type's constructors. Some people said that inline functions do away with the need for inheriting the constructors. The same argument can be applied to any inherited function. I don't think that this is a valid argument: explicitly rewriting function (headers) means you are not using inheritance. Someone said that they had never needed this feature in their code. Here is a real life example from the InterViews X windows library. The class PushButton has six different constructors defined for it. It has a (inherited) virtual function "Press" that is called when the button is pressed (actually, when it is released). A simple way to get a specific desired behavior for a PushButton is to create a new class "MyPushButton" and redefine the virtual function "Press" to do what you want. The *only* new behavior this class introduces is for the Press function. Why should "MyPushButton" have to (re)introduce the six constructors that are defined for "PushButton". At the C++ conference this fall, it was mentioned that a "complete" language description was supposed to be floating around among some of the "inside" parties this spring. Does this reference manual exist in some preliminary form and if so, does it discuss whether constructors are inherited in a correct implementation of c++? For completeness, an example showing the "maybe" nature of inheriting constructors is shown below. I tried this example on cfront 1.2.1 and on g++ (v 1.27?). Neil Soiffer Textronix Computer Research Lab ARPA: soiffer@CRL.TEK.COM UUCP: ...!tektronix!tekchips!soiffer ----------------- #include <stdio.h> class B { public: B(int n) {i=n;}; void f() {printf("f of B\n");}; protected: int i; }; class D: public B { public: void f() {printf("f of D\n");}; }; class VirtualB { // cfront won't accept this class def without a constructor // difference from class B above is that the function is a virtual function. public: VirtualB(int n) {i=n;}; virtual void vf() {printf("vf of VirtualB\n");}; protected: int i; }; class VirtualD: public VirtualB { public: virtual void vf() {printf("vf of VirtualD\n");}; }; main() { D d_obj(3); // works for both d_obj.f(); VirtualD vd_obj(3); // works for g++, not cfront vd_obj.vf(); D d_obj2 = D(3); // works for cfront, not g++ d_obj2.f(); VirtualD vd_obj2 = VirtualD(3); // doesn't work for either vd_obj2.vf(); }
turner@sdti.SDTI.COM (Prescott K. Turner) (01/27/89)
In article <3477@tekcrl.CRL.TEK.COM>, soiffer@tekcrl.CRL.TEK.COM (Neil Soiffer) says: > [...] the program that I included that showed that in cfront, they > [constructors] are occasionally inherited What cfront does with your example seems very odd. I've heard it said so often that constructors are not inherited that I can't point out when Dr. Stroustrup said it. This non-inheritance is intentional. What's more, you are looking not just for constructors to be inherited, but to be accessible by the name of the derived class. Such a feature is not described in the book or in any of the other papers describing the definition of C++. > In Stroustrup's book, the only comment on the first form "D d(5)" that > I could find is on page 139, saying that the first form is an abbreviation > of the second form. Why should an abbreviation behave differently than > the full form? Indeed cfront treats them identically in the sample program you present. It's g++ which handles them differently, and it's a bug. > The *only* new behavior this class introduces is for the Press function. > Why should "MyPushButton" have to (re)introduce the six constructors that > are defined for "PushButton". Yes, good example. > Does this reference manual exist in some preliminary > form and if so, does it discuss whether constructors are inherited in a > correct implementation of c++? Yes, where I work we are lucky to be among the reviewers of the revised reference manual for C++. It is not finished, so reviewing it has its price as well as benefits. I can't comment on what it says about inheritance of constructors, but if it is silent we will mention that in our review. -- Prescott K. Turner, Jr. Software Development Technologies, Inc. 375 Dutton Rd., Sudbury, MA 01776 USA (508) 443-5779 UUCP: ...{harvard,mit-eddie}!sdti!turner Internet: turner@sdti.sdti.com