Thread overview | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 07, 2006 [Bug 91] New: Inherited classes require base class to have a default constructor. | ||||
---|---|---|---|---|
| ||||
http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 Summary: Inherited classes require base class to have a default constructor. Product: D Version: 0.152 Platform: PC OS/Version: Windows Status: NEW Severity: minor Priority: P2 Component: DMD AssignedTo: bugzilla@digitalmars.com ReportedBy: eric96@gmail.com Let me know if this is expected behavior or some rule I don't know about, but I think it's a bug. If you insert the default constructor "this(){}" in A, it compiles fine. // Looks like it requires the base class to have a default constructor. class A { this (int i) // constructor yage.a.this(int) does not match argument types () {} } class B : A { this (int i) {} } Also, Windows XP SP2; Haven't tried it on Linux yet. -- |
April 07, 2006 Re: [Bug 91] New: Inherited classes require base class to have a default constructor. | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | d-bugmail@puremagic.com wrote: > http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 > > Summary: Inherited classes require base class to have a default > constructor. > Product: D > Version: 0.152 > Platform: PC > OS/Version: Windows > Status: NEW > Severity: minor > Priority: P2 > Component: DMD > AssignedTo: bugzilla@digitalmars.com > ReportedBy: eric96@gmail.com > > > Let me know if this is expected behavior or some rule I don't know about, but I think it's a bug. If you insert the default constructor "this(){}" in A, it compiles fine. > > // Looks like it requires the base class to have a default constructor. > class A > { this (int i) // constructor yage.a.this(int) does not match argument types > () > {} > } > class B : A > { this (int i) > {} > } This is correct behaviour. Class B implicitly calls the default constructor and if one is not found, an appropriate parent class constructor call should be explicitly defined in B's constructor. -- Jari-Matti |
April 07, 2006 [Bug 91] Inherited classes require base class to have a default constructor. | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 smjg@iname.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |smjg@iname.com Status|NEW |RESOLVED Resolution| |INVALID ------- Comment #1 from smjg@iname.com 2006-04-07 05:30 ------- The compiler is correctly diagnosing an error. The derived class needs a base class constructor to call. The keyword "super", when used in a constructor, denotes a constructor of the base class. class B : A { this (int i) { super(i); } } If no call to super is present, then it looks for a default constructor and calls that. Hence if there's no default constructor in the base class, then you must call super when calling the derived class. -- |
April 07, 2006 [Bug 91] Inherited classes require base class to have a default constructor. | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 ------- Comment #2 from eric96@gmail.com 2006-04-07 11:33 ------- I'm familiar with super(), but I incorrectly thought that I could completely override the constructor in the parent class, as it works with other methods. Is this behavior consistent with other oo languages? -- |
April 07, 2006 [Bug 91] Inherited classes require base class to have a default constructor. | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 ------- Comment #3 from smjg@iname.com 2006-04-07 11:55 ------- Yes, including C++ and Java. If anybody could circumvent the requirement to use a constructor simply by creating a derived a class, it would defeat the point. You can, however, put a protected constructor in the base class. This is a constructor created specifically for derived classes to base their constructors on. You would be able to completely override* a constructor if the base class has a protected constructor that does nothing. But can you think of an example in which this would make sense? * Actually, constructors don't override as such. A constructor is a member only of the class in which it is defined, not of any derived classes. Hence if the base class has no default constructor, then when deriving a class from it you must explicitly define a constructor. -- |
April 08, 2006 D's constructor call hierarchy (Was: Re: [Bug 91] Inherited classes require base class to have a default constructor.) | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | d-bugmail@puremagic.com wrote: > http://d.puremagic.com/bugzilla/show_bug.cgi?id=91 > > > ------- Comment #3 from smjg@iname.com 2006-04-07 11:55 ------- > Yes, including C++ and Java. If anybody could circumvent the requirement to > use a constructor simply by creating a derived a class, it would defeat the > point. > > You can, however, put a protected constructor in the base class. This is a > constructor created specifically for derived classes to base their constructors > on. You would be able to completely override* a constructor if the base class > has a protected constructor that does nothing. But can you think of an example > in which this would make sense? > > * Actually, constructors don't override as such. A constructor is a member > only of the class in which it is defined, not of any derived classes. Hence if > the base class has no default constructor, then when deriving a class from it > you must explicitly define a constructor. > > Ok, so the spec says: "If there is no constructor for a class, but there is a constructor for the base class, a default constructor of the form: this() { } is implicitly generated." But why is this? Why must a derived class have it's own constructor, explicit or not? I don't think this makes sense. One time, I wanted to create a new exception class, just to throw around and make use of it's class type. So it didn't have any new content. I coded: class MyException : Exception { } ... and surprised I was when this didn't compile, as it isn't valid code. (Because an implicit constructor "this() { }" is inserted, but there isn't a super constructor with 0 parameters). Seems to me this idea of inserting an implicit default constructor doesn't make sense, yet both Java and C# have this behavior (and C++ for what was said), so can it be I'm missing something? :/ -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D |
April 08, 2006 Re: D's constructor call hierarchy (Was: Re: [Bug 91] Inherited classes require base class to have a default constructor.) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros | Bruno Medeiros wrote:
> d-bugmail@puremagic.com wrote:
>
>> http://d.puremagic.com/bugzilla/show_bug.cgi?id=91
>>
>>
>> ------- Comment #3 from smjg@iname.com 2006-04-07 11:55 -------
>> Yes, including C++ and Java. If anybody could circumvent the requirement to
>> use a constructor simply by creating a derived a class, it would defeat the
>> point.
>>
>> You can, however, put a protected constructor in the base class. This is a
>> constructor created specifically for derived classes to base their constructors
>> on. You would be able to completely override* a constructor if the base class
>> has a protected constructor that does nothing. But can you think of an example
>> in which this would make sense?
>>
>> * Actually, constructors don't override as such. A constructor is a member
>> only of the class in which it is defined, not of any derived classes. Hence if
>> the base class has no default constructor, then when deriving a class from it
>> you must explicitly define a constructor.
>>
>>
>
> Ok, so the spec says:
>
> "If there is no constructor for a class, but there is a constructor for the base class, a default constructor of the form:
> this() { }
> is implicitly generated."
>
> But why is this? Why must a derived class have it's own constructor, explicit or not? I don't think this makes sense. One time, I wanted to create a new exception class, just to throw around and make use of it's class type. So it didn't have any new content. I coded:
>
> class MyException : Exception { }
>
> ... and surprised I was when this didn't compile, as it isn't valid code. (Because an implicit constructor "this() { }" is inserted, but there isn't a super constructor with 0 parameters). Seems to me this idea of inserting an implicit default constructor doesn't make sense, yet both Java and C# have this behavior (and C++ for what was said), so can it be I'm missing something? :/
>
Yeah. This is bothersome sometimes; but it also has the property of allowing one to hide superclass ctors. There are other way to do that, such as composition, but it can be handy at times.
I wondered, since we're stuck with the "alias" idiom, whether it could be used to expose subclassed ctors in a manner similar to overloaded method names:
class Super
{
this (int i) {}
}
class Sub : Super
{
alias super._ctor _ctor;
}
A bit fugly, but you get the idea.
|
April 08, 2006 Re: D's constructor call hierarchy (Was: Re: [Bug 91] Inherited classes require base class to have a default constructor.) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros | Bruno Medeiros wrote: > > Ok, so the spec says: > > "If there is no constructor for a class, but there is a constructor for the base class, a default constructor of the form: > this() { } > is implicitly generated." > > But why is this? Why must a derived class have it's own constructor, explicit or not? As far as I know, all classes have an implicit this() ctor if no ctor is explicitly defined. Otherwise it would be impossible to instantiate the class. I don't think this makes sense. One time, I wanted to > create a new exception class, just to throw around and make use of it's class type. So it didn't have any new content. I coded: > > class MyException : Exception { } > > ... and surprised I was when this didn't compile, as it isn't valid code. (Because an implicit constructor "this() { }" is inserted, but there isn't a super constructor with 0 parameters). A derived class is responsible for passing the appropriate parameters to its base class for initialization. This is done automatically when the base class has no explicit ctor or has a zero-parameter ctor, but otherwise you have to do this explicitly. Seems to me this > idea of inserting an implicit default constructor doesn't make sense, yet both Java and C# have this behavior (and C++ for what was said), so can it be I'm missing something? :/ C++ has this behavior as well. In fact, a default ctor, copy ctor, and assignment operator are all generated if no ctor or assignment operator are explicitly defined. Sean |
April 09, 2006 Re: D's constructor call hierarchy (Was: Re: [Bug 91] Inherited classes require base class to have a default constructor.) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > Bruno Medeiros wrote: >> >> Ok, so the spec says: >> >> "If there is no constructor for a class, but there is a constructor for the base class, a default constructor of the form: >> this() { } >> is implicitly generated." >> >> But why is this? Why must a derived class have it's own constructor, explicit or not? > > As far as I know, all classes have an implicit this() ctor if no ctor is explicitly defined. Otherwise it would be impossible to instantiate the class. It's not true (that "it would be impossible to instantiate the class."), since for derived classes a super constructor could be used to instantiate it. > > I don't think this makes sense. One time, I wanted to >> create a new exception class, just to throw around and make use of it's class type. So it didn't have any new content. I coded: >> >> class MyException : Exception { } >> >> ... and surprised I was when this didn't compile, as it isn't valid code. (Because an implicit constructor "this() { }" is inserted, but there isn't a super constructor with 0 parameters). > > A derived class is responsible for passing the appropriate parameters to its base class for initialization. This is done automatically when the base class has no explicit ctor or has a zero-parameter ctor, but otherwise you have to do this explicitly. > > Seems to me this >> idea of inserting an implicit default constructor doesn't make sense, yet both Java and C# have this behavior (and C++ for what was said), so can it be I'm missing something? :/ > > C++ has this behavior as well. In fact, a default ctor, copy ctor, and assignment operator are all generated if no ctor or assignment operator are explicitly defined. > > > Sean If the derived class initializing is the same as the base class, I shouldn't have to repeat myself. For that code (MyException) I have to do the following, which is redundant: class MyException : Exception { this(char[] msg) { super(msg); } } also, this reuse has to be done for all super constructors that one wants to be available on the derived class. And... hum... Damn... I've just answered myself. This design allows "one to hide superclass ctors", just like kris said, but only now did I get it. I guess that's the reason why the new languages have that behavior? Hum, what's it like in non-C-family OO languages like Ruby and Python, anyone knows ? (Also, DMD could print a better message when an inserted implicit super() is not found.) -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D |
April 09, 2006 Re: D's constructor call hierarchy (Was: Re: [Bug 91] Inherited classes require base class to have a default constructor.) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros | Bruno Medeiros wrote: > If the derived class initializing is the same as the base class, I shouldn't have to repeat myself. For that code (MyException) I have to do the following, which is redundant: > > class MyException : Exception { > this(char[] msg) { > super(msg); > } > } I think there's a valid point here, namely that one shouldn't be forced to type boiler-plate code like this -- for the same reason, many IDEs can generate declarations like this automatically. Constructors are not methods, and thus aren't inherited (since neither D nor C++ have the notion of virtual constructors), and of course it should be possible to prevent instantiation of subclasses using superclass constructors, for obvious reasons. But I've never understood why, if no constructors are defined explicitly, only the zero-argument constructor is automatically defined ("inherited" if you will), and not _all_ of the superclass constructors. Take for instance a subclass of Error. Error itself defines two constructors (one taking a message, and one additionally taking another Error, for exception chaining), and a subclass might want to do the same. With a constructor-less definition like class MyError : Error { } I don't see why both of Error's constructors could not implicitly be defined. Of course, if one specified one or more constructors, no implicit constructors should be defined. (On an unrelated note, shouldn't Exception also support exception chaining?) -- Søren J. Løvborg web@kwi.dk |
Copyright © 1999-2021 by the D Language Foundation