Modern C++: confused with constructors inheritance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Beach Potato

    Modern C++: confused with constructors inheritance

    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::Derive d() { /*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::Derive d() { printf("Derived "); }

    void main() { Derived d; }

    would return "BaseDerive d"
    -------------------------------------------

    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.

  • 4Space

    #2
    Re: Modern C++: confused with constructors inheritance

    > But in VC++ the keyword "override" is not defined, and no matter what I[color=blue]
    > do with constructors, results are always the same:
    > -------------------------------------------
    > class Base { public: Base(); };
    > Base::Base() { printf("Base"); }
    > class Derived : Base { public: Derived(); };
    > Derived::Derive d() { printf("Derived "); }
    >
    > void main() { Derived d; }
    >
    > would return "BaseDerive d"
    > -------------------------------------------[/color]

    derived is not a C++ keyword, and I certainly haven't seen it anywhere in
    C++.
    [color=blue]
    > 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?[/color]

    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.
    [color=blue]
    >
    > I'm somewhat confused here.
    >[/color]

    You and me both :¬)

    Cheers,

    4Space


    Comment

    • Kevin Goodsell

      #3
      Re: Modern C++: confused with constructors inheritance

      Beach Potato wrote:
      [color=blue]
      > 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.[/color]

      Constructors cannot be inherited or overridden (since they cannot be
      virtual).
      [color=blue]
      >
      > 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; };[/color]

      'override' is not defined.
      [color=blue]
      > Derived::Derive d() { /*inherited;*/ printf("Derived "); }
      >
      > void main() { Derived d; }[/color]

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

      After fixing your code, it printed "BaseDerive d" which is what I
      expected. The default Base constructor is used to initialize the 'Base'
      part of d.
      [color=blue]
      >
      > ///
      > 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).[/color]

      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.
      [color=blue]
      >
      > 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::Derive d() { printf("Derived "); }
      >
      > void main() { Derived d; }
      >
      > would return "BaseDerive d"[/color]

      Technically the behavior is undefined, but after fixing the obvious
      problems that would be the expected output.
      [color=blue]
      > -------------------------------------------
      >
      > 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?[/color]

      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
      --
      My email address is valid, but changes periodically.
      To contact me please use the address from a recent posting.

      Comment

      • Alf P. Steinbach

        #4
        Re: Modern C++: confused with constructors inheritance

        On Thu, 11 Sep 2003 20:06:54 +0530, "Josephine Schafer" <jsf@usa.net> wrote:[color=blue]
        >
        >"jeffc" <nobody@nowhere .com> wrote in message
        >news:3f6082cf_ 2@news1.prserv. net...[color=green]
        >>
        >> There isn't *any* way to override constructors, with the given language
        >> elements. Overriding constructors would require virtual constructors, and
        >> that doesn't exist in C++. Do a search on "virtual constructor" to see if
        >> you can find a simulation of this behavior.[/color]
        >
        >Well, Scott Meyers does discuss simulatiom of virtual constructors in More
        >Effective C++ (Item 25).
        >May be that help the OP.[/color]


        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.

        Comment

        • Beach Potato

          #5
          Re: Modern C++: confused with constructors inheritance

          4Space wrote:[color=blue][color=green]
          >>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::Derive d() { printf("Derived "); }
          >>
          >>void main() { Derived d; }
          >>
          >>would return "BaseDerive d"
          >>-------------------------------------------[/color]
          >
          >
          > derived is not a C++ keyword, and I certainly haven't seen it anywhere in
          > C++.[/color]

          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.

          4Space wrote:[color=blue]
          > Overriding a constructor would be a very bad idea. It totally violates any
          > encapsulation. Why exactly do you need to do it?[/color]

          Kevin Goodsell wrote:[color=blue]
          > Basically the question is (as it often is in this group): What do you
          > *really* want to do?[/color]

          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.


          Comment

          • Alf P. Steinbach

            #6
            Re: Modern C++: confused with constructors inheritance

            On Thu, 11 Sep 2003 19:36:48 GMT, Beach Potato <wired_dntsndsp m_beachpotato@y ahoo.com> wrote:
            [color=blue]
            >Kevin Goodsell wrote:[color=green]
            > > Basically the question is (as it often is in this group): What do you
            > > *really* want to do?[/color]
            >
            >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[/color]

            It is a feature; see the FAQ 23.3
            <url:http://www.parashift.c om/c++-faq-lite/strange-inheritance.htm l#faq-23.3>

            [color=blue]
            >and constructors are not a good place to run class-specific initialization
            >procedures.[/color]

            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 ApiWindowFactor y
            {
            public:
            virtual WindowHandle create() const { /*...*/ }
            };
            public:
            GeneralWindow( ApiWindowFactor y const& aFactory = ApiWindowFactor y() )
            {
            // ...
            myHandle = aFactory.create ();
            }
            };


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

            class ApiButtonFactor y: public Base::ApiWindow Factory
            {
            public:
            virtual WindowHandle create() const { /*...*/ }
            };
            public:
            Button( ApiButtonFactor y const& aFactory = ApiButtonFactor y() )
            : Base( aFactory )
            {
            }
            };


            See also the FAQ 23.4
            <url:http://www.parashift.c om/c++-faq-lite/strange-inheritance.htm l#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.at t.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"... ;-) )

            Comment

            • 4Space

              #7
              Re: Modern C++: confused with constructors inheritance

              > A typical example - a class that implements Microsoft Windows window. If[color=blue]
              > 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.[/color]

              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.
              [color=blue]
              > 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.[/color]

              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


              Comment

              • tom_usenet

                #8
                Re: Modern C++: confused with constructors inheritance

                On Thu, 11 Sep 2003 19:36:48 GMT, Beach Potato
                <wired_dntsndsp m_beachpotato@y ahoo.com> wrote:
                [color=blue]
                >4Space wrote:[color=green][color=darkred]
                >>>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::Derive d() { printf("Derived "); }
                >>>
                >>>void main() { Derived d; }
                >>>
                >>>would return "BaseDerive d"
                >>>-------------------------------------------[/color]
                >>
                >>
                >> derived is not a C++ keyword, and I certainly haven't seen it anywhere in
                >> C++.[/color]
                >
                >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.[/color]

                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.
                [color=blue]
                >
                >4Space wrote:[color=green]
                >> Overriding a constructor would be a very bad idea. It totally violates any
                >> encapsulation. Why exactly do you need to do it?[/color]
                >
                >Kevin Goodsell wrote:[color=green]
                > > Basically the question is (as it often is in this group): What do you
                > > *really* want to do?[/color]
                >
                >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.[/color]

                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...
                [color=blue]
                >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
                >initializati on procedures.[/color]

                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

                Comment

                Working...