Modern C++: confused with constructors inheritance

B

Beach Potato

I guess I've been out of C++ for a while, since right now I don't seem
to get a simple solution for overriding inherited constrictors.

What worked in Borland C++ & Pascal (and Java, if I remember correctly) as:
-------------------------------------------
class Base { public: Base(); };
Base::Base() { printf("Base"); }

class Derived : Base { public: Derived(); override; };
Derived::Derived() { /*inherited;*/ printf("Derived"); }

void main() { Derived d; }

///
would return "Derived"
-------------------------------------------
I could control whether I wanted to use base constructor or not with
keywords "override" and "inherited" (if I took the comments out from the
Derived constructor).

But in VC++ the keyword "override" is not defined, and no matter what I
do with constructors, results are always the same:
-------------------------------------------
class Base { public: Base(); };
Base::Base() { printf("Base"); }
class Derived : Base { public: Derived(); };
Derived::Derived() { printf("Derived"); }

void main() { Derived d; }

would return "BaseDerived"
-------------------------------------------

Is there any way to make the derived constructor fully override the
base? I tried all combinations with public/protected/private to no
avail. Something very simple without an intricate C++ implementation,
that only hardcore C++ folks can understand?

I'm somewhat confused here.
 
4

4Space

But in VC++ the keyword "override" is not defined, and no matter what I
do with constructors, results are always the same:
-------------------------------------------
class Base { public: Base(); };
Base::Base() { printf("Base"); }
class Derived : Base { public: Derived(); };
Derived::Derived() { printf("Derived"); }

void main() { Derived d; }

would return "BaseDerived"
-------------------------------------------

derived is not a C++ keyword, and I certainly haven't seen it anywhere in
C++.
Is there any way to make the derived constructor fully override the
base? I tried all combinations with public/protected/private to no
avail. Something very simple without an intricate C++ implementation,
that only hardcore C++ folks can understand?

Overriding a constructor would be a very bad idea. It totally violates any
encapsulation. Why exactly do you need to do it? I don't think I've ever
seen any OOP language that has this ability. And I suspect this is a
tautology, insomuch that any language with this functionality could not be
OO.
I'm somewhat confused here.

You and me both :¬)

Cheers,

4Space
 
K

Kevin Goodsell

Beach said:
I guess I've been out of C++ for a while, since right now I don't seem
to get a simple solution for overriding inherited constrictors.

Constructors cannot be inherited or overridden (since they cannot be
virtual).
What worked in Borland C++ & Pascal (and Java, if I remember correctly) as:
-------------------------------------------
class Base { public: Base(); };
Base::Base() { printf("Base"); }

class Derived : Base { public: Derived(); override; };

'override' is not defined.
Derived::Derived() { /*inherited;*/ printf("Derived"); }

void main() { Derived d; }

In C++, main returns int. void has never been an acceptable return type
for main.

After fixing your code, it printed "BaseDerived" which is what I
expected. The default Base constructor is used to initialize the 'Base'
part of d.
///
would return "Derived"

I'm not aware of any way you could have achieved that in C++. override
and inherited have never been C++ keywords, to the best of my knowledge.
But in VC++ the keyword "override" is not defined, and no matter what I
do with constructors, results are always the same:
-------------------------------------------
class Base { public: Base(); };
Base::Base() { printf("Base"); }
class Derived : Base { public: Derived(); };
Derived::Derived() { printf("Derived"); }

void main() { Derived d; }

would return "BaseDerived"

Technically the behavior is undefined, but after fixing the obvious
problems that would be the expected output.
-------------------------------------------

Is there any way to make the derived constructor fully override the
base? I tried all combinations with public/protected/private to no
avail. Something very simple without an intricate C++ implementation,
that only hardcore C++ folks can understand?

There is no way at all. At least not in those terms. I mean, I'm sure
what you want to finally accomplish is possible, but not via overriding
constructors, since that is not possible in C++. It also doesn't make
sense - the 'Base' part of a 'Derived' object must be initialized
somehow. The constructor is how that happens. You can use whatever
constructor you want (by 'calling' it in the initialization list for
'Derived's constructor), but if you don't specify, the default will be
used. If there is no default, the program will fail to compile.

Basically the question is (as it often is in this group): What do you
*really* want to do?

-Kevin
 
A

Alf P. Steinbach

Well, Scott Meyers does discuss simulatiom of virtual constructors in More
Effective C++ (Item 25).
May be that help the OP.


Virtual constructors as well as dynamic binding during initialization
(DBDI) / dynamic binding during construction (DBDC) are also in the FAQ.

Unfortunately not collected into a single topic.

But perhaps we're the discussing the wrong thing; if I recall correctly
the OP asked about _inherited constrictors_, i.e. the monster snakes.
 
B

Beach Potato

4Space said:
derived is not a C++ keyword, and I certainly haven't seen it anywhere in
C++.

I was talking about words "override" and "inherited", that do exist in
some OOP languages. In Pascal, for instance, the default behaviour is to
"override" the constructor (so this keyword is not included in the
language), so you have to specify when and where in the constructor you
want to call the base, like:

constructor Derived.Init;
begin
Other_Func();
inherited Init;
end;

In this case, for instance, you call it after you initialization, not
before. Or you can even not call it at all. That makes you responsible,
of course, for the initialization of all Base variables.
Overriding a constructor would be a very bad idea. It totally violates any
encapsulation. Why exactly do you need to do it?

Kevin said:
Basically the question is (as it often is in this group): What do you
*really* want to do?

A typical example - a class that implements Microsoft Windows window. If
you place the initialization routines in a Base constructor, it
registers the default window class and then creates the actual window.
If you derive a class to represent a different type of a window, you
could hope that the Derived constructor would do a different routine,
and that you'll create a single new window, not both - Derived and Base.
So I guess, if unability to break the execution is a C++ limitation or
feature, and constructors are not a good place to run class-specific
initialization procedures.
 
A

Alf P. Steinbach

Kevin said:
Basically the question is (as it often is in this group): What do you
*really* want to do?

A typical example - a class that implements [a] window. If
you place the initialization routines in a Base constructor, it
registers the default window class and then creates the actual window.
If you derive a class to represent a different type of a window, you
could hope that the Derived constructor would do a different routine,
and that you'll create a single new window, not both - Derived and Base.
So I guess, if unability to break the execution is a C++ limitation or
feature

It is a feature; see the FAQ 23.3
and constructors are not a good place to run class-specific initialization
procedures.

On the contrary, that's exactly where class-specific initialization should
be.

Unfortunately most C++ GUI frameworks have been inspired by less typesafe
languages, but here's one way (and the way I prefer) for doing exactly the
kind of thing that you _really_ want to do, in a typesafe manner:


class GeneralWindow
{
protected:
WindowHandle myHandle;

class ApiWindowFactory
{
public:
virtual WindowHandle create() const { /*...*/ }
};
public:
GeneralWindow( ApiWindowFactory const& aFactory = ApiWindowFactory() )
{
// ...
myHandle = aFactory.create();
}
};


class Button: public GeneralWindow
{
protected:
typedef GeneralWindow Base;

class ApiButtonFactory: public Base::ApiWindowFactory
{
public:
virtual WindowHandle create() const { /*...*/ }
};
public:
Button( ApiButtonFactory const& aFactory = ApiButtonFactory() )
: Base( aFactory )
{
}
};


See also the FAQ 23.4
<url:http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>

(Heya Marshall, t'was a good thing to include that, not? But although that
discussion's over, wrt. to 'init' method I'd still like to see a reference to
<url:http://www.research.att.com/~bs/3rd_safe.pdf> section E.3.5, on why
an 'init'-method is generally a very very bad idea, not to say "evil"... ;-) )
 
4

4Space

A typical example - a class that implements Microsoft Windows window. If
you place the initialization routines in a Base constructor, it
registers the default window class and then creates the actual window.
If you derive a class to represent a different type of a window, you
could hope that the Derived constructor would do a different routine,
and that you'll create a single new window, not both - Derived and Base.

Well, I'm not sure exactly what you are trying to do. But perhaps
parameterised protected constructors would help - allowing your derived
classes to pass more information to the base class object. It may just be
that aggregation rather than inheritance is what you want.
So I guess, if unability to break the execution is a C++ limitation or
feature, and constructors are not a good place to run class-specific
initialization procedures.

Like Alf said - constructors *ARE* the place to do this. But base classes
are responsible for deciding what derived classes can an cannot change.

Cheers

4Space
 
T

tom_usenet

I was talking about words "override" and "inherited", that do exist in
some OOP languages. In Pascal, for instance, the default behaviour is to
"override" the constructor (so this keyword is not included in the
language), so you have to specify when and where in the constructor you
want to call the base, like:

constructor Derived.Init;
begin
Other_Func();
inherited Init;
end;

In this case, for instance, you call it after you initialization, not
before. Or you can even not call it at all. That makes you responsible,
of course, for the initialization of all Base variables.

This can't really work in C++. C++ has a much more strict construction
model due to the existence of "value" types. When you enter your
constructor body, all your bases and all your members have already
been constructed. As a result, if a base class constructor does
something in particular, then all classes derived from that are stuck
with it. Hence, if the base class needs to be configurable, it should
be via passed in parameters that the derived classes can create as
they like.

In the languages you are talking about, can the derived class
constructors modify the value of base class private members? If so,
I'd consider the feature extremely dangerous, and if not, it's a bit
useless.
A typical example - a class that implements Microsoft Windows window. If
you place the initialization routines in a Base constructor, it
registers the default window class and then creates the actual window.

Are you saying that this Window is hard coded, and can't be modified
to a Window of choice by passing different parameters to the
constructor? That sounds like a useless Window base class...
If you derive a class to represent a different type of a window, you
could hope that the Derived constructor would do a different routine,
and that you'll create a single new window, not both - Derived and Base.
So I guess, if unability to break the execution is a C++ limitation or
feature, and constructors are not a good place to run class-specific
initialization procedures.

On the contrary, constructors are an excellent place to do
initialization, since it allows you to increase the number of class
invariants which should help reduce bugs. However, you can't hard code
behaviour in the constructor if you want it to be modifiable by
derived classes - make the behaviour configurable by passing in
different parameters.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top