Const member initialization list question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Wolfram Humann

    Const member initialization list question

    Hi,

    please don't be too harsh if I made stupid errors creating this simple
    example from my more complex case.

    Suppose I have a class like this:

    class BOOK
    {
    const string title;
    const string author;
    const int pages;
    const double price;

    static map<string, BOOK> MyBooks;

    BOOK(const string& title_, const string& author_,
    const int pages_, const double price_);

    BOOK(const string& title_);

    const BOOK& findByTitle(con st string& title);
    }

    I fill the map with books created by the 4-argument constructor. I use
    findByTitle to look up books in the map. My problem is with the
    constructor that takes a title. About the only way to define this
    seems to be:

    BOOK::BOOK(cons t string& title_)
    : title(title_),
    author(findByTi tle(title_).aut hor)
    pages(findByTit le(title_).page s)
    price(findByTit le(title_).pric e)
    {}

    The problem is that findByTitle is called 3 times. That's not very
    efficient. If my members were non-const I could do

    BOOK::BOOK(cons t string& title_)
    : title(title_)
    {
    BOOK book = findByTitle(tit le_);
    author = book.author;
    pages = book.pages;
    price = book.price;
    }

    But since my books don't have a habit of suddenly changing their
    author, I think those members *should* be const. Any elegant
    solutions?

    Thanks,
    Wolfram
  • Victor Bazarov

    #2
    Re: Const member initialization list question

    "Wolfram Humann" <whumann@gmx.de > wrote...[color=blue]
    > please don't be too harsh if I made stupid errors creating this simple
    > example from my more complex case.
    >
    > Suppose I have a class like this:
    >
    > class BOOK
    > {
    > const string title;
    > const string author;
    > const int pages;
    > const double price;[/color]

    Should price really be 'const'? Never mind...
    [color=blue]
    >
    > static map<string, BOOK> MyBooks;[/color]

    public:
    [color=blue]
    >
    > BOOK(const string& title_, const string& author_,
    > const int pages_, const double price_);
    >
    > BOOK(const string& title_);
    >
    > const BOOK& findByTitle(con st string& title);[/color]

    This should probably be 'static'.
    [color=blue]
    > }[/color]
    ;

    I hope those three suggestions are not an indicator of my being harsh.
    [color=blue]
    >
    > I fill the map with books created by the 4-argument constructor. I use
    > findByTitle to look up books in the map. My problem is with the
    > constructor that takes a title. About the only way to define this
    > seems to be:
    >
    > BOOK::BOOK(cons t string& title_)
    > : title(title_),
    > author(findByTi tle(title_).aut hor)
    > pages(findByTit le(title_).page s)
    > price(findByTit le(title_).pric e)
    > {}
    >
    > The problem is that findByTitle is called 3 times. That's not very
    > efficient. If my members were non-const I could do
    >
    > BOOK::BOOK(cons t string& title_)
    > : title(title_)
    > {
    > BOOK book = findByTitle(tit le_);[/color]

    BOOK const & book = findByTitle(tit le_); // more efficient
    [color=blue]
    > author = book.author;
    > pages = book.pages;
    > price = book.price;
    > }
    >
    > But since my books don't have a habit of suddenly changing their
    > author, I think those members *should* be const. Any elegant
    > solutions?[/color]

    You have to answer the question: why do I need to construct another
    object from a single 'title' when I already have one sitting in the
    map<string, BOOK>? As soon as you can answer that, we'll be able to
    give you an elegant solution. Deal?

    Victor


    Comment

    • Wolfram Humann

      #3
      Re: Const member initialization list question

      On Tue, 09 Sep 2003 17:18:57 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
      wrote:[color=blue]
      >
      > You have to answer the question: why do I need to construct another
      > object from a single 'title' when I already have one sitting in the
      > map<string, BOOK>? As soon as you can answer that, we'll be able to
      > give you an elegant solution. Deal?
      >
      > Victor
      >
      >[/color]

      Suppose the user of the class wants to say:
      (assuming the book is already in the map, error otherwise)

      BOOK stroustrup("The C++ Programming Language");
      cout << "Stroustrup has " << stroustrup.page s << " pages" << endl;

      or I have

      LIBRARY::addBoo k(BOOK book);

      myLibrary.addBo ok("The C++ Programming Language");

      I already found that here I need a BOOK::BOOK(cons t char* title_) (with
      char* instead of string) constructor. I think the reason is that otherwise
      I have an implicit conversion chain with two user-defined conversions...?

      Wolfram

      Comment

      • Howard

        #4
        Re: Const member initialization list question


        "Wolfram Humann" <whumann@gmx.de > wrote in message
        news:opru8ttxa1 1udsjr@netnews. ..[color=blue]
        > On Tue, 09 Sep 2003 17:18:57 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
        > wrote:[color=green]
        > >
        > > You have to answer the question: why do I need to construct another
        > > object from a single 'title' when I already have one sitting in the
        > > map<string, BOOK>? As soon as you can answer that, we'll be able to
        > > give you an elegant solution. Deal?
        > >
        > > Victor
        > >
        > >[/color]
        >
        > Suppose the user of the class wants to say:
        > (assuming the book is already in the map, error otherwise)
        >
        > BOOK stroustrup("The C++ Programming Language");
        > cout << "Stroustrup has " << stroustrup.page s << " pages" << endl;
        >
        > or I have
        >
        > LIBRARY::addBoo k(BOOK book);
        >
        > myLibrary.addBo ok("The C++ Programming Language");
        >
        > I already found that here I need a BOOK::BOOK(cons t char* title_) (with
        > char* instead of string) constructor. I think the reason is that otherwise
        > I have an implicit conversion chain with two user-defined conversions...?
        >
        > Wolfram[/color]

        It seems to me that addBook (in the second case at least) should do the
        lookup for the book given the title, and error out if it is not found. Then
        it can create a new instance (or copy-create it, or use a reference to the
        the existing one) based on the one it finds. I'm not sure what you want to
        happen in the first case, since you haven't provided a constructor with no
        parameters, and you're in effect adding an "unknown" book to the library.
        (Also, shouldn't the map be a member of your library class, not a member of
        the book class itself? It seems strange to have a book that has a
        collection of books in it, doesn't it?)

        -Howard




        Comment

        • Victor Bazarov

          #5
          Re: Const member initialization list question

          "Wolfram Humann" <whumann@gmx.de > wrote...[color=blue]
          > On Tue, 09 Sep 2003 17:18:57 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
          > wrote:[color=green]
          > >
          > > You have to answer the question: why do I need to construct another
          > > object from a single 'title' when I already have one sitting in the
          > > map<string, BOOK>? As soon as you can answer that, we'll be able to
          > > give you an elegant solution. Deal?
          > >
          > > Victor
          > >
          > >[/color]
          >
          > Suppose the user of the class wants to say:
          > (assuming the book is already in the map, error otherwise)
          >
          > BOOK stroustrup("The C++ Programming Language");
          > cout << "Stroustrup has " << stroustrup.page s << " pages" << endl;
          >
          > or I have
          >
          > LIBRARY::addBoo k(BOOK book);
          >
          > myLibrary.addBo ok("The C++ Programming Language");
          >
          > I already found that here I need a BOOK::BOOK(cons t char* title_) (with
          > char* instead of string) constructor. I think the reason is that otherwise
          > I have an implicit conversion chain with two user-defined conversions...?[/color]

          Doesn't convince me. If you need to find out whether it's there or not,
          use 'find'. If it's there, you will get it, if it's not, you can either
          rely on an exception thrown, or a NULL pointer return value. If you know
          it's not there, construct by giving all needed arguments. If you know
          that it's there, no need to construct another object.

          Victor


          Comment

          • Wolfram Humann

            #6
            Re: Const member initialization list question

            On Tue, 09 Sep 2003 21:30:03 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
            wrote:[color=blue]
            >
            > Doesn't convince me. If you need to find out whether it's there or not,
            > use 'find'. If it's there, you will get it, if it's not, you can either
            > rely on an exception thrown, or a NULL pointer return value. If you know
            > it's not there, construct by giving all needed arguments. If you know
            > that it's there, no need to construct another object.
            >
            > Victor
            >[/color]

            O.k., I see your point: a constructor should make new objects -- why use
            it when the object is already there.

            Well, for the users of my class these are like new objects as they have
            never seen them. My real case is not about books but an abstraction of
            some electronic hardware. The map is pre-filled with the available modules
            without interaction of the class's user. Maybe that's a weak argument...

            For named objects I think at least a copy-constructor is required, even
            when findByTitle is used instead of a constructor:

            BOOK tolkien( findByTitle("Th e Hobbit") );

            Also the constructor taking a title is somewhat convenient. Compare:

            cout << BOOK("The Hobbit").author ;
            cout << BOOK::findByTit le("The Hobbit").author ;
            (Of course .author needs to be replaced by an access function)

            Finally for historical reasons I don't have a choice: I have to provide
            this constructor to be consistent with existing software, even if it's not
            the most logical thing to do.

            My question remains: Can I play any (dirty?) tricks to avoid looking up my
            map three times. (Knowing that this should not really work I tried
            assigning to "this" in the initializer list or calling a copy constructor.
            Of course that failed.)

            If nothing else helps, I would consider making my members non-const or
            putting them all in a struct and initialize that struct in the
            constructors initialization list:

            BOOK::BOOK(cons t string& title)
            : memberStruct(fi ndByTitle(title ).memberStruct)
            {}

            Comment

            • Howard

              #7
              Re: Const member initialization list question


              "Wolfram Humann" <whumann@gmx.de > wrote in message
              news:oprvapw1e0 1udsjr@netnews. ..[color=blue]
              > On Tue, 09 Sep 2003 21:30:03 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
              > wrote:[color=green]
              > >
              > > Doesn't convince me. If you need to find out whether it's there or not,
              > > use 'find'. If it's there, you will get it, if it's not, you can either
              > > rely on an exception thrown, or a NULL pointer return value. If you[/color][/color]
              know[color=blue][color=green]
              > > it's not there, construct by giving all needed arguments. If you know
              > > that it's there, no need to construct another object.
              > >
              > > Victor
              > >[/color]
              >
              > O.k., I see your point: a constructor should make new objects -- why use
              > it when the object is already there.
              >
              > Well, for the users of my class these are like new objects as they have
              > never seen them. My real case is not about books but an abstraction of
              > some electronic hardware. The map is pre-filled with the available modules
              > without interaction of the class's user. Maybe that's a weak argument...
              >[/color]

              I'm not even sure what that argument means. What is a "user" of your class?
              Another programmer? An end-user? Or code that makes calls to your class's
              code? I don't see what having "never seen them" means in relation to any of
              those cases. And I still don't see why you need to construct a new instance
              of an object if the object already exists, because all that is doing is
              making a copy of some existing object, and your limited example of using
              that copy does not justify that action.

              Plus, you still haven't explained what a LIBRARY is (nor why your collection
              of BOOKs is contained in a BOOK object instead of a LIBRARY object).
              [color=blue]
              > For named objects I think at least a copy-constructor is required, even
              > when findByTitle is used instead of a constructor:
              >
              > BOOK tolkien( findByTitle("Th e Hobbit") );
              >[/color]

              I don't understand what you mean when you say "even when findByTitle is used
              instead of a constructor". A copy-constructor takes a const reference to an
              existing object (a BOOK) and creates a new one based on that. It's
              irrelevant how you obtained that reference.
              [color=blue]
              > Also the constructor taking a title is somewhat convenient. Compare:
              >
              > cout << BOOK("The Hobbit").author ;
              > cout << BOOK::findByTit le("The Hobbit").author ;[/color]

              Is findByTitle a static function??? Why are you specifying
              BOOK::findByTit le, and not something like someBook.findBy Title? This seems
              to point tight back to the use of another class (LIBRARY) to hold the
              collection instead of an individual BOOK.
              [color=blue]
              > (Of course .author needs to be replaced by an access function)
              >
              > Finally for historical reasons I don't have a choice: I have to provide
              > this constructor to be consistent with existing software, even if it's not
              > the most logical thing to do.
              >[/color]

              Well, the mere existence of a constructor that takes just the title instead
              of all its members does not mean that you have to *always* use that
              constructor to use such a book. Assuming that findByTitle returns a
              reference to an existing BOOK object (does it?), then you might want to do
              this:

              BOOK& someOtherBook = someBook.findBy Title("The Hobbit");
              cout << someOtherBook.a uthor << endl;
              cout << someOtherBook.p rice << endl;

              There's no construction going on here at all, and I only need the
              findByTitle call once.

              (Or if findByTitle returns a pointer, then use a pointer instead of a
              reference...but my point is the same.)
              [color=blue]
              > My question remains: Can I play any (dirty?) tricks to avoid looking up my
              > map three times. (Knowing that this should not really work I tried
              > assigning to "this" in the initializer list or calling a copy constructor.
              > Of course that failed.)
              >
              > If nothing else helps, I would consider making my members non-const or
              > putting them all in a struct and initialize that struct in the
              > constructors initialization list:
              >
              > BOOK::BOOK(cons t string& title)
              > : memberStruct(fi ndByTitle(title ).memberStruct)
              > {}[/color]

              I think your example is just too abstracted to make any sense as it relates
              to the actual problem that you have. But it looks like you've answered your
              own question: if you MUST use this constructor and need to initialize it via
              findByTitle, then using the result of that call to initialize (construct) a
              member struct appears to me to be a good way. But in that case, you'll end
              up doing exactly what we've been suggesting: calling findByTitle to get a
              pointer or reference to an existing BOOK, and passing that pointer or
              reference to a constructor (in this case the constructor of that new struct,
              instead of a new BOOK object).


              Without a more realistic sample of your code and the problem you face,
              (especially showing the context in which you feel the need to use a newly
              constructed object like that instead of a pointer or reference), I doubt we
              can tell you any more than you already know.

              (Sorry if I sound argumentative here....don't mean to.)

              -Howard



              Comment

              • Karl Heinz Buchegger

                #8
                Re: Const member initialization list question



                Wolfram Humann wrote:[color=blue]
                >[/color]
                I still believe you have a design flaw.

                A single book is not a collection of books.
                There should be 2 distinct classes: book - library

                You don't ask a book to find some title. You ask a library
                to look up if there is a book with a specific title.

                Therefore the problem you are now facing simply disappears
                if you correct the design.

                LIBRARY MyLibrary;

                BOOK* pBook = MyLibrary.FindB yTitle( "TheHobbit" );

                // if the book is in the library, you now have a pointer to it.

                if( pBook )
                cout << pBook->author;
                else {
                cout << "I don't have that book. Please provide the details to create it\n";
                cin >> author;

                MyLibrary.Add( BOOK( "The Hobbit", author ) );
                }

                --
                Karl Heinz Buchegger
                kbuchegg@gascad .at

                Comment

                • Wolfram Humann

                  #9
                  Re: Const member initialization list question

                  I started writing a reply but can't stay long enough today to finish it.
                  Hopefully tomorrow will be less busy. Sorry.

                  Wolfram

                  Comment

                  • Wolfram Humann

                    #10
                    Re: Const member initialization list question

                    On 10 Sep 2003 20:49:01 GMT, Howard <alicebt@hotmai l.com> wrote:[color=blue]
                    >
                    > I'm not even sure what that argument means. What is a "user" of your
                    > class?
                    > Another programmer? An end-user? Or code that makes calls to your
                    > class's
                    > code? I don't see what having "never seen them" means in relation to
                    > any of
                    > those cases. And I still don't see why you need to construct a new
                    > instance
                    > of an object if the object already exists, because all that is doing is
                    > making a copy of some existing object, and your limited example of using
                    > that copy does not justify that action.[/color]

                    First of all: I highly appreciate all the efforts (yours and those of
                    Victor and Karl Heinz) to help me. This discussion provided me with a
                    number of good points to think about in my design. But I think I see that
                    my limited example may not be sufficient. And my employer might not
                    appreciate if I post the original code ;-). I tried to invent a simple
                    case and now we are more into a discussion of that case's design than into
                    my original problem. I'll still try to explain what I can. If it's more
                    confusing than illuminating, just tell me I'm a hopeless case and abort
                    the discussion...

                    The "users" are other programmers. At the beginning of their sourcecode
                    they (naturally) don't have any BOOK objects. But the map of books is
                    already filled. Maybe they even will not be allowed to add other books
                    (the constructor taking enough arguments to create a fully defined BOOK
                    may be private). So how do they make BOOK objects? I proposed a
                    constructor taking a title that returns a copy of an existing book:

                    BOOK tolkien("The Hobbit");

                    If I understand Victor correctly, his point is that a constructor should
                    create something new and not return something existing. I suppose he would
                    prefer using a function like findByTitle() that returns an existing book.
                    If findByTitle() is static, as Victor proposed, that would work for
                    nameless objects:

                    cout << BOOK::findByTit le("The Hobbit").author ;

                    But how do I create named objects? I don't expect to have a default
                    constructor (is there a default book?). So the only way to create a named
                    object would be to copy-construct from a nameless object returned by
                    findByTitle():

                    BOOK tolkien( findByTitle("Th e Hobbit") );

                    [color=blue]
                    > Plus, you still haven't explained what a LIBRARY is (nor why your
                    > collection
                    > of BOOKs is contained in a BOOK object instead of a LIBRARY object).[/color]

                    O.k., forget about LIBRARY. I invented it quickly and it was a bad
                    example. Objects of my second class contain a subset of by "books",
                    LIBRARY would be more like a superset. I'll try to invent something better
                    a few lines down :-)
                    My collection of BOOKs is NOT contained in any BOOK object. It's static,
                    so it's contained in the class. I think that's not too bad -- each object
                    contains a single book, the class has a collection of all my books.

                    If my second class contains a subset of my books, maybe a good example
                    could be BOOKSHELF or GENRE. Let's try GENRE. My only point here was, if
                    GENRE has a method addBook() that takes a BOOK as an argument, then with
                    the constructor I proposed I could say:

                    GENRE fantasy;
                    fantasy.addBook ("The Hobbit");

                    otherwise I have to say

                    fantasy.addBook ( findByTitle("Th e Hobbit") );

                    I like that first form, but that's just personal preference.
                    [color=blue][color=green]
                    >> For named objects I think at least a copy-constructor is required, even
                    >> when findByTitle is used instead of a constructor:
                    >>
                    >> BOOK tolkien( findByTitle("Th e Hobbit") );
                    >>[/color]
                    >
                    > I don't understand what you mean when you say "even when findByTitle is
                    > used
                    > instead of a constructor". A copy-constructor takes a const reference
                    > to an
                    > existing object (a BOOK) and creates a new one based on that. It's
                    > irrelevant how you obtained that reference.[/color]

                    Victor wrote: "why do I need to construct another object from a single
                    'title' when I already have one sitting in the map<string, BOOK>?" My
                    point was: The objects in the map are nameless. If somebody wants a named
                    BOOK object, he will need some kind of contructor to create it. Either the
                    contructor taking a title, as I proposed, or a copy constructor as
                    mentioned above.
                    [color=blue][color=green]
                    >> Also the constructor taking a title is somewhat convenient. Compare:
                    >>
                    >> cout << BOOK("The Hobbit").author ;
                    >> cout << BOOK::findByTit le("The Hobbit").author ;[/color]
                    >
                    > Is findByTitle a static function??? Why are you specifying
                    > BOOK::findByTit le, and not something like someBook.findBy Title? This
                    > seems
                    > to point tight back to the use of another class (LIBRARY) to hold the
                    > collection instead of an individual BOOK.[/color]

                    1. findByTitle() wasn't static in my first post. But I think Victor
                    pointed out correctly that it should be.
                    2. How do I construct your someBook?
                    [color=blue]
                    > Assuming that findByTitle returns a
                    > reference to an existing BOOK object (does it?),[/color]
                    Yes, it does.[color=blue]
                    > then you might want to do this:
                    >
                    > BOOK& someOtherBook = someBook.findBy Title("The Hobbit");
                    > cout << someOtherBook.a uthor << endl;
                    > cout << someOtherBook.p rice << endl;
                    >
                    > There's no construction going on here at all, and I only need the
                    > findByTitle call once.
                    >
                    > (Or if findByTitle returns a pointer, then use a pointer instead of a
                    > reference...but my point is the same.)[/color]

                    I'm a bit reluctant to use pointers or references to objects in my map. I
                    don't think that current implementations will ever reallocate memory as
                    they grow. The nodes of the underlying tree have pointers to parent, left
                    and right, so it's sufficient to manipulate those pointers during groth.
                    But is this behavior guaranteed by any standard?

                    How was someBook created? Maybe like this:

                    BOOK someBook( findByTitle("Pr ogramming Perl") );

                    Now does it make sense to say:

                    someBook.findBy Title("The Hobbit"); ?

                    I would prefer to use findByTitle() as a static function:

                    BOOK::findByTit le("The Hobbit");
                    [color=blue]
                    > Without a more realistic sample of your code and the problem you face,
                    > (especially showing the context in which you feel the need to use a newly
                    > constructed object like that instead of a pointer or reference), I doubt
                    > we can tell you any more than you already know.[/color]

                    O.k.. I just thought that I might have overseen some very simple solution.

                    Again, thank you for this discussion. If forced me to think again about
                    some aspects of my design and that's always good!

                    Wolfram

                    Comment

                    • Victor Bazarov

                      #11
                      Re: Const member initialization list question

                      "Wolfram Humann" <whumann@gmx.de > wrote...[color=blue]
                      > [...] At the beginning of their sourcecode
                      > they (naturally) don't have any BOOK objects. But the map of books is
                      > already filled. [...][/color]

                      Here is what I fail to understand. What is the map filled with
                      if there are no BOOK objects? If you can answer that, you can
                      probably give a better description of your problem. Try.

                      Victor


                      Comment

                      • Wolfram Humann

                        #12
                        Re: Const member initialization list question

                        On Sun, 14 Sep 2003 03:56:53 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
                        wrote:
                        [color=blue]
                        > "Wolfram Humann" <whumann@gmx.de > wrote...[color=green]
                        >> [...] At the beginning of their sourcecode
                        >> they (naturally) don't have any BOOK objects. But the map of books is
                        >> already filled. [...][/color]
                        >
                        > Here is what I fail to understand. What is the map filled with
                        > if there are no BOOK objects? If you can answer that, you can
                        > probably give a better description of your problem. Try.
                        >
                        > Victor
                        >[/color]

                        How about this case: There's a static member

                        BOOK::defineBoo k(const string& title, const string& author,
                        const int pages, const double price);

                        It is usually called at the beginning of the source-code. It uses a
                        (private?) constructor to create BOOK objects and puts them into the map.
                        So the objets are there but how can I access them? The key of the map is
                        the title, so I think access should be by title. Suppose I know there is a
                        BOOK in the map titled "The Hobbit". How do I create a BOOK object
                        "tolkien" that refers to that book? My idea was:

                        BOOK tolkien("The Hobbit");

                        That requires a constructor taking a title that retrieves books form the
                        map.

                        O.K., I tried. Is it any clearer now? :-)

                        Wolfram

                        Comment

                        • Howard

                          #13
                          Re: Const member initialization list question


                          "Wolfram Humann" <whumann@gmx.de > wrote in message
                          news:oprvds08c3 1udsjr@netnews. ..

                          I still don't think that there is any reason to construct a new object at
                          all, unless you are adding it to your map. If you're just inquiring for
                          information about an existing book, then simply return a reference to one.
                          If there is a chance that the book might not exist, then either throw an
                          exception and handle it, or else return a pointer instead of a reference,
                          and make it nil when the specified book doesn't exist. Regardless of
                          whether you're getting a "named" variable or not, that's just the logical
                          way of doing it. For example,:

                          (using a returned reference, and trapping for the exception:)

                          try
                          {
                          cout << BOOK::findByTit le("The Hobbit").author ;
                          cout << BOOL::findByTit le("The Hobbit").publis her;
                          }
                          catch(...)
                          {
                          // ...error? create and add a new one?
                          }

                          (very inefficient, since it looks up the book twice, but still there is no
                          constructor being used),

                          OR (better, in my opinion, using a returned pointer which *may* be nil)...

                          BOOK* someBook = BOOK:findByTitl e("The Hobbit");
                          if (someBook)
                          {
                          cout << someBook->author;
                          cout << someBook->publisher;
                          }
                          else
                          {
                          // ...error? create and add a new one?
                          }

                          This second design is just much more logical. But notice that in neither
                          case is there any construction going on. If you need to add a book that is
                          NOT in the map, then you'll already have all that info at hand, and can
                          simply call the constructor that takes the whole set of required information
                          as parameters, with no need to look up whether a book exists or not during
                          construction, because you've already checked fact that via the static
                          findByTitle function.

                          Hope this helps..

                          -Howard







                          Comment

                          • Karl Heinz Buchegger

                            #14
                            Re: Const member initialization list question



                            Wolfram Humann wrote:[color=blue]
                            >
                            > On Sun, 14 Sep 2003 03:56:53 GMT, Victor Bazarov <v.Abazarov@att Abi.com>
                            > wrote:
                            >[color=green]
                            > > "Wolfram Humann" <whumann@gmx.de > wrote...[color=darkred]
                            > >> [...] At the beginning of their sourcecode
                            > >> they (naturally) don't have any BOOK objects. But the map of books is
                            > >> already filled. [...][/color]
                            > >
                            > > Here is what I fail to understand. What is the map filled with
                            > > if there are no BOOK objects? If you can answer that, you can
                            > > probably give a better description of your problem. Try.
                            > >
                            > > Victor
                            > >[/color]
                            >
                            > How about this case: There's a static member
                            >
                            > BOOK::defineBoo k(const string& title, const string& author,
                            > const int pages, const double price);
                            >
                            > It is usually called at the beginning of the source-code. It uses a
                            > (private?) constructor to create BOOK objects and puts them into the map.
                            > So the objets are there but how can I access them? The key of the map is
                            > the title, so I think access should be by title. Suppose I know there is a
                            > BOOK in the map titled "The Hobbit". How do I create a BOOK object
                            > "tolkien" that refers to that book? My idea was:
                            >
                            > BOOK tolkien("The Hobbit");
                            >
                            > That requires a constructor taking a title that retrieves books form the
                            > map.
                            >
                            > O.K., I tried. Is it any clearer now? :-)[/color]

                            You still have not figured out, that you have a design error.
                            A single book is not a library of books. Nor does one single
                            book contain the whole library.

                            There should be 2 classes:
                            BOOK and LIBRARY

                            --
                            Karl Heinz Buchegger
                            kbuchegg@gascad .at

                            Comment

                            • Wolfram Humann

                              #15
                              Re: Const member initialization list question

                              On 16 Sep 2003 19:00:07 GMT, Howard <alicebt@hotmai l.com> wrote:
                              [color=blue]
                              > If you're just inquiring for information about an existing book,
                              > then simply return a reference to one [...], or else return a
                              > pointer instead of a reference, and make it nil when the
                              > specified book doesn't exist.[/color]

                              I see your point and I agree that this is a clean solution. Two remarks:

                              1. I still could not find any statement in the standard that
                              references/pointers to map entries will always remain valid when the map
                              grows/shrinks. As I said, I don't think the current implementation of a
                              map will reallocate memory (like e.g. the vector does) but I don't want to
                              rely on this unless the standard defines that it's illegal for a map to
                              reallocate memory for its entries.

                              2. Using references or pointes may be more logical than creating
                              "redundant" objects but at least for my current project I won't be able to
                              do this. My code has to remain consistent with existing code.

                              Wolfram

                              Comment

                              Working...