Not calling base class constructors

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • st_ev_fe@hotmail.com

    #1

    Not calling base class constructors

    I've noticed that when constructing a subclass, the base class get's
    it's contructors called.

    Is there some way to avoid this? The base class has one variable, which
    gets initialised to 0.

    The subclass's constructor sets this variable to a real value.

    So first the variable is set to 0, the variable is never used before it
    once again gets set to a real value. It's a waste. Any ideas anyone?

  • Sumit Rajan

    #2
    Re: Not calling base class constructors


    <st_ev_fe@hotma il.com> wrote in message
    news:1132061742 .341827.61890@g 43g2000cwa.goog legroups.com...[color=blue]
    > I've noticed that when constructing a subclass, the base class get's
    > it's contructors called.
    >
    > Is there some way to avoid this? The base class has one variable, which
    > gets initialised to 0.
    >
    > The subclass's constructor sets this variable to a real value.
    >
    > So first the variable is set to 0, the variable is never used before it
    > once again gets set to a real value. It's a waste. Any ideas anyone?[/color]


    You could try something similar to following:

    class Base {
    int mem;
    public:
    Base(int val = 0) : mem(val) {}
    };

    class Derived : public Base {
    public:
    Derived(int a = 0) : Base(a) {}
    };

    Regards,
    Sumit.
    --
    Sumit Rajan <sumitr@msdc.hc ltech.com>

    Regards,
    Sumit.
    --
    Sumit Rajan sumitr@msdc.hcl tech.com


    Comment

    • werasm

      #3
      Re: Not calling base class constructors


      st_ev_fe@hotmai l.com wrote:[color=blue]
      > I've noticed that when constructing a subclass, the base class get's
      > it's contructors called.[/color]

      Yes, that is supposed to happen as the base is instantiated before the
      derived.
      [color=blue]
      >
      > Is there some way to avoid this? The base class has one variable, which
      > gets initialised to 0.[/color]

      No.
      [color=blue]
      >
      > The subclass's constructor sets this variable to a real value.[/color]

      Why does the base class constructor not set it? How does the derived
      class set it - with a setter, I hope. We don't want protected members
      :-).
      [color=blue]
      >
      > So first the variable is set to 0, the variable is never used before it
      > once again gets set to a real value. It's a waste. Any ideas anyone?[/color]

      Initialise it by forwarding the parameter to the base constructor.

      class Base
      {
      public:
      explicit Base(int mem): mem_( mem ){ ; }
      //The rest of bases interface...omi tted - perhaps includes
      // virtual ~Base, depending on whether want to delete
      // via Base.
      int getMem() const;
      void setMem();

      private:
      int mem_;
      };

      class Derived : public Base
      {
      public:
      explicit Derived( int mem ): Base( mem ){}
      //etc...
      };

      Comment

      • st_ev_fe@hotmail.com

        #4
        Re: Not calling base class constructors

        OK I'd like it to work like this:

        GenericObject obj; // internal member is 0.
        StringObject str = "hello world"; // string object is a subclass of
        GenericObject

        So basically, StringObject needs to be constructed via the constructor
        and not via a setter. Otherwise it will be awkward.

        However doing this will set it's internal member twice, once to 0 and
        then the second time to a real pointer.

        Comment

        • mlimber

          #5
          Re: Not calling base class constructors

          st_ev_fe@hotmai l.com wrote:[color=blue]
          > OK I'd like it to work like this:
          >
          > GenericObject obj; // internal member is 0.
          > StringObject str = "hello world"; // string object is a subclass of
          > GenericObject
          >
          > So basically, StringObject needs to be constructed via the constructor
          > and not via a setter. Otherwise it will be awkward.
          >
          > However doing this will set it's internal member twice, once to 0 and
          > then the second time to a real pointer.[/color]

          First, have you shown with a profiler that this is really an issue? It
          sounds to me like you are worried about something that probably doesn't
          matter and are prematurely optimizing. Are you sure that your optimizer
          doesn't strip the first initialization anyway?

          Second, can you use the solution mentioned by Sumit and werasm? It
          would only initialize the parameter once.

          Cheers! --M

          Comment

          • Andrey Tarasevich

            #6
            Re: Not calling base class constructors

            st_ev_fe@hotmai l.com wrote:[color=blue]
            > OK I'd like it to work like this:
            >
            > GenericObject obj; // internal member is 0.
            > StringObject str = "hello world"; // string object is a subclass of
            > GenericObject
            >
            > So basically, StringObject needs to be constructed via the constructor
            > and not via a setter. Otherwise it will be awkward.
            >
            > However doing this will set it's internal member twice, once to 0 and
            > then the second time to a real pointer.[/color]

            You have to provide more details. What "internal member" you are talking about?
            Is that the member intended to store the pointer to the string in the
            'StringObject'? If that's the case, then why is that "internal member" declared
            as high in the class hierarchy as 'GenericObject' ? Or is it something else?

            --
            Best regards,
            Andrey Tarasevich

            Comment

            • John Harrison

              #7
              Re: Not calling base class constructors

              st_ev_fe@hotmai l.com wrote:[color=blue]
              > OK I'd like it to work like this:
              >
              > GenericObject obj; // internal member is 0.
              > StringObject str = "hello world"; // string object is a subclass of
              > GenericObject
              >
              > So basically, StringObject needs to be constructed via the constructor
              > and not via a setter. Otherwise it will be awkward.
              >
              > However doing this will set it's internal member twice, once to 0 and
              > then the second time to a real pointer.
              >[/color]

              class GenericObject
              {
              public:
              GenericObject() : internal_member (0) {}
              GenericObject(c onst void* ptr) : internal_member (ptr) {}
              };

              class StringObject : public GenericObject
              {
              public:
              StringObject(co nst char* str) : GenericObject(s tr) {}
              };

              What's is the problem with this solution? Answering this will perhaps
              help solve your real problem.

              john

              Comment

              • John Harrison

                #8
                Re: Not calling base class constructors

                >[color=blue]
                > class GenericObject
                > {
                > public:
                > GenericObject() : internal_member (0) {}
                > GenericObject(c onst void* ptr) : internal_member (ptr) {}[/color]

                private:
                const void* internal_member ;[color=blue]
                > };
                >[/color]

                I meant this of course.

                John

                Comment

                • st_ev_fe@hotmail.com

                  #9
                  Re: Not calling base class constructors

                  I don't have a problem with the solution in the sense that I am against
                  it.

                  however, I am unsure of how it works.

                  class StringObject : public GenericObject
                  {
                  public:
                  StringObject(co nst char* str) : GenericObject(s tr) {}
                  };

                  To me, that looks like GenericObject() will be called, twice.

                  Think about it:

                  StringObject(co nst char* str) {
                  ; // no code here
                  }

                  This constructor will actually still allow the base class's constructor
                  to be called, right?


                  StringObject(co nst char* str) : member(SomeFunc tion(str)) {
                  ; // no code here
                  }

                  This constructor first gets it's internal member set to 0, and then set
                  to the result of SomeFunction.

                  So by explicitly calling the base class's constructor function, isn't
                  the base constructor being called twice?

                  Or is there some sort of self-inconsistancy in C++ specifically
                  designed to say that if you specifiy the base class's constructor
                  within the initialisor, it doesn't get called twice? If so, what are
                  the limits to this rule? If you call the constructor twice within the
                  initiailiser does it still get called once, or twice?

                  What if you call a base constructor in the initialiser that has a
                  different signiture than our derived class's constructor? Does the
                  base's constructor still only get called once or twice?

                  I'm just rather new to C++'s details.

                  Comment

                  • werasm

                    #10
                    Re: Not calling base class constructors


                    st_ev_fe@hotmai l.com wrote:[color=blue]
                    > OK I'd like it to work like this:
                    >
                    > GenericObject obj; // internal member is 0.
                    > StringObject str = "hello world"; // string object is a subclass of
                    > GenericObject
                    >
                    > So basically, StringObject needs to be constructed via the constructor
                    > and not via a setter. Otherwise it will be awkward.[/color]

                    Usually ABC's (Abstract Base Classes) or interfaces (which is mostly
                    why you require inheritance) are accessed via pointer or reference.
                    Your example here above is a little skimpy to comment, but the fact
                    that you have implementation in your Base is dubious already.
                    [color=blue]
                    >
                    > However doing this will set it's internal member twice, once to 0 and
                    > then the second time to a real pointer.[/color]
                    This is not true, there is only on member and it is only set once - as
                    the example showed. Besides, even if there were to, as someone else
                    already stated - std::string uses copy on write semantics - chances are
                    that there would very little overhead regardless as memory between two
                    strings in case below...

                    std::string s1( "Hallo World" );
                    std::string s2( s1 );

                    .... is shared - if s1 goes out of scope before s2, then s2 will
                    effectively own the contents of the string created by s1.

                    string s2;
                    //begin scope
                    {
                    string s1( "Hallo world." );
                    s2 = s1;

                    }//end scope

                    //At this point, chances are quite good that s2 now
                    // owns the memory originally created by s1 due to COW.

                    Give us a better example :0

                    GenericObject obj; // internal member is 0.
                    ??? Why do you instantiate generic object, weird and suspect.

                    StringObject str = "hello world"; // string object is a subclass of
                    As StringObject inherits (publicly) from GenericObject, it <is a>
                    GenericObject, therefore the GenericObject member (that forms
                    part of StringObject) is initialised. No need to instantiate generic
                    object explicitly

                    GenericObject ??? What - this is invalid/meaningless code/example

                    Regards,

                    W

                    Comment

                    • Karl Heinz Buchegger

                      #11
                      Re: Not calling base class constructors

                      st_ev_fe@hotmai l.com wrote:[color=blue]
                      >
                      > I don't have a problem with the solution in the sense that I am against
                      > it.
                      >
                      > however, I am unsure of how it works.
                      >
                      > class StringObject : public GenericObject
                      > {
                      > public:
                      > StringObject(co nst char* str) : GenericObject(s tr) {}
                      > };
                      >
                      > To me, that looks like GenericObject() will be called, twice.[/color]

                      It isn't.

                      While the abover looks like a function call, it isn't one.
                      The compiler calls the base class constructor for you in any
                      case. But here you can specify which one to use, just in case
                      there are more then one to choose from; or/and you have the
                      ability to pass arguments to the choosen constructor.

                      [color=blue]
                      >
                      > Think about it:
                      >
                      > StringObject(co nst char* str) {
                      > ; // no code here
                      > }
                      >
                      > This constructor will actually still allow the base class's constructor
                      > to be called, right?[/color]

                      Yes. If you don't specify which one to use, the compiler always
                      uses the so called default constructor.
                      [color=blue]
                      >
                      > StringObject(co nst char* str) : member(SomeFunc tion(str)) {
                      > ; // no code here
                      > }
                      >
                      > This constructor first gets it's internal member set to 0, and then set
                      > to the result of SomeFunction.[/color]

                      No.
                      The compiler will choose a constructor for member, which allows passing
                      the result of SomeFuntion() to it.
                      [color=blue]
                      >
                      > So by explicitly calling the base class's constructor function, isn't
                      > the base constructor being called twice?[/color]

                      You don't call the base class constructor explicite. You can't call
                      a constructor, since it is not an ordinary function (I know, Alf.
                      Please do me a favour don't respond to this).

                      But you can specify *which* constructor, out of many you want the compiler
                      to choose and you can pass arguments when doing so.

                      Summary:
                      A base class constructor is called in any case. But you have the oportunity
                      to guide the compiler which one it should be.

                      --
                      Karl Heinz Buchegger
                      kbuchegg@gascad .at

                      Comment

                      • werasm

                        #12
                        Re: Not calling base class constructors

                        Sorry, here it is again (hopefully) without typos...
                        [color=blue]
                        > OK I'd like it to work like this:[/color]
                        [color=blue]
                        > GenericObject obj; // internal member is 0.
                        > StringObject str = "hello world"; // string object is a subclass of
                        > GenericObject[/color]

                        [color=blue]
                        > So basically, StringObject needs to be constructed via the constructor
                        > and not via a setter. Otherwise it will be awkward.[/color]

                        Usually ABC's (Abstract Base Classes) or interfaces (which is mostly
                        why you require inheritance) are accessed via pointer or reference.
                        Your example here above is a little skimpy to comment, but the fact
                        that you have implementation in your Base is dubious already.
                        [color=blue]
                        > However doing this will set it's internal member twice, once to 0 and
                        > then the second time to a real pointer.[/color]


                        This is not true, there is only one member and it is only set once - as

                        the example showed. Besides, even if there were two, as someone else
                        already stated, std::string uses copy on write (COW) semantics. Chances
                        are
                        that there would be very little overhead regardless, as memory between
                        two
                        strings in case below...

                        std::string s1( "Hallo World" );
                        std::string s2( s1 );


                        .... is shared - if s1 goes out of scope before s2, then s2 will
                        effectively own the contents of the string created by s1.

                        //e.g.
                        string s2;
                        //begin scope
                        {
                        string s1( "Hallo world." );
                        s2 = s1;

                        }//end scope

                        //At this point, chances are quite good that s2 now
                        // owns the memory originally created by s1 due to COW.

                        //end e.g.

                        I must state that this behaviour is only applicable to strings because
                        they are implemented that way (with COW semantics). You cannot assume
                        this for all types having dynamic memory (incase you did not know :-)
                        ).

                        Furthermore ...

                        Give us a better example :0. Given your original example (by line):

                        GenericObject obj; // internal member is 0.
                        ??? Why do you instantiate GenericObject, weird and suspect.
                        ....
                        - Remember, instantiating the derived automatically first instantiates
                        the base.

                        StringObject str = "hello world"; // string object is a subclass of
                        ....
                        As StringObject inherits (publicly) from GenericObject, it <is a>
                        GenericObject, therefore the GenericObject member (that forms
                        part of StringObject) is initialised. No need to instantiate generic
                        object explicitly.


                        GenericObject ??? What - this is invalid/meaningless code/example

                        Regards,

                        Werner

                        Comment

                        • Kaz Kylheku

                          #13
                          Re: Not calling base class constructors

                          st_ev_fe@hotmai l.com wrote:[color=blue]
                          > I've noticed that when constructing a subclass, the base class get's
                          > it's contructors called.
                          >
                          > Is there some way to avoid this? The base class has one variable, which
                          > gets initialised to 0.
                          >
                          > The subclass's constructor sets this variable to a real value.
                          >
                          > So first the variable is set to 0, the variable is never used before it
                          > once again gets set to a real value. It's a waste. Any ideas anyone?[/color]

                          The solution is to design the base class for inheritance. When you are
                          designing a class to be used as a base class, you have to create
                          intelligent constructors that will be useful for the derived class
                          authors.

                          That way you don't have to assign to a member variable after the base
                          class constructor runs: you invoke the right base class constructor
                          where you can pass down the value that will go into that variable.


                          class Base {
                          protected:
                          int x, y;

                          Base(int xv, int yv);
                          public:
                          Base();
                          };

                          In this class, there is a public default constructor for the world to
                          use. It initializes the protected members x and y with some default
                          values. The member variables are not accessible from the outside.

                          But, a derived class has access to x and y. This is deliberately so.
                          And for that reason, a constructor is provided which initializes x and
                          y. The derived class authors might want different initial values for
                          these variables, and not the defaults that are set up in the default
                          constructor used by the rest of the world, so in the derived class:


                          class Derived : public Base {
                          public:
                          // initialize members x and y with 40 and 50
                          Derived() : Base(40, 50) { /* ... */ }
                          };

                          You call the base class constructor from the derived one using the
                          above syntax in the initializer list.

                          In general, you have to be quite flexible about initialization. If your
                          initialization is too encapsulated, life is difficult for derived class
                          writers: they have to allow your default initializations to occur, and
                          then mutate the object in various ways. Sometimes, those extra steps
                          can be quite expensive.

                          Imagine a GUI object which sets up a whole ton of defaults by calling
                          the window system. The derived object then has to make a whole ton of
                          more calls to override those defaults.

                          E.g. suppose a text widget object creates a default font. It calls the
                          GUI framework to search for the font by name, size, boldness, and other
                          attributes. It constructs the font object and retains the handle, etc.
                          Then, the derived class wants a different default font. Oops! So we
                          deallocate that one, and do it all over again ... It could all be
                          avoided by taking the font parameters through the constructor, or
                          providing two-step initialization.

                          Comment

                          Working...