Class forname in c++

Discussion in 'C++' started by Manuel, Sep 13, 2006.

  1. Manuel

    Manuel Guest

    hi,

    In the past I made the question "how to implement a simple class
    forname". I made this finally and it compiled well. but now when i
    execute the program, it crash with a sigsegv.

    The code is this:

    FACTORY_H

    typedef Object * (*PtrMethod)(std::vector<std::string>);

    class Factory
    {
    private:
    map<const char*, PtrMethod*, ltstr> theMap;

    protected:
    Factory();

    ~Factory();

    Object * method1(std::vector<std::string>);
    Object * method2(std::vector<std::string>);

    public:
    Object *
    getObject(std::string,std::vector<std::string>);

    };

    FACTORY_CPP

    Factory::Factory()
    {
    map["method1"] = &method1;
    map["method2"] = &method2;

    }

    Object * Factory::getObject(string label,vector<string> paramaters)
    {
    PtrMethod method = theMap[label];
    Object * object = (*method)(parameters); <- crash here.
    return object;

    }

    ==================================================

    has somebody an idea? why does it crash?
     
    Manuel, Sep 13, 2006
    #1
    1. Advertising

  2. Manuel

    mlimber Guest

    Manuel wrote:
    > hi,
    >
    > In the past I made the question "how to implement a simple class
    > forname". I made this finally and it compiled well. but now when i
    > execute the program, it crash with a sigsegv.
    >
    > The code is this:
    >
    > FACTORY_H
    >
    > typedef Object * (*PtrMethod)(std::vector<std::string>);
    >
    > class Factory
    > {
    > private:
    > map<const char*, PtrMethod*, ltstr> theMap;
    >
    > protected:
    > Factory();
    >
    > ~Factory();
    >
    > Object * method1(std::vector<std::string>);
    > Object * method2(std::vector<std::string>);
    >
    > public:
    > Object *
    > getObject(std::string,std::vector<std::string>);
    >
    > };
    >
    > FACTORY_CPP
    >
    > Factory::Factory()
    > {
    > map["method1"] = &method1;
    > map["method2"] = &method2;
    >
    > }
    >
    > Object * Factory::getObject(string label,vector<string> paramaters)
    > {
    > PtrMethod method = theMap[label];
    > Object * object = (*method)(parameters); <- crash here.
    > return object;
    >
    > }
    >
    > ==================================================
    >
    > has somebody an idea? why does it crash?


    Yes. It's because you're using map<>::eek:perator[]() to look-up the
    value, and then you dereference the pointer without checking for null.
    As you'll note in footnote 3 of SGI's description of the STL
    (http://www.sgi.com/tech/stl/Map.html#3), if the key in question is not
    found in the map, that operator does an insert, initializing the
    corresponding value to its default (in this case, a null pointer).
    That's generally not what you want.

    What you should be doing is calling std::map<>::find() to do your
    lookup, and then make sure the value was found:

    std::auto_ptr<Object> Factory::getObject(
    const string& label,
    const vector<string>& paramaters)
    {
    typedef map<const char*, PtrMethod*, ltstr> MyMap;
    const MyMap::const_iterator iter = theMap.find( label );
    if( iter == theMap.end() )
    {
    return std::auto_ptr<Object>( 0 );
    }

    const PtrMethod method = iter->second;
    return std::auto_ptr<Object>( (*method)(parameters) );
    }

    Note also that I changed the return type to std::auto_ptr so that the
    caller knows it is responsible to cleanup that pointer, and I changed
    the function parameters to const references to avoid unnecessary and
    possibly expensive copies. You should do likewise in your member
    functions above.

    Cheers! --M
     
    mlimber, Sep 13, 2006
    #2
    1. Advertising

  3. Manuel wrote:
    > In the past I made the question "how to implement a simple class
    > forname". I made this finally and it compiled well. but now when i
    > execute the program,


    I don't think your code below is a complete C++ program. You might
    want to consider posting the whole thing before asking for help with
    "your program".

    > it crash with a sigsegv.
    >
    > The code is this:
    >
    > FACTORY_H
    >
    > typedef Object * (*PtrMethod)(std::vector<std::string>);
    >
    > class Factory
    > {
    > private:
    > map<const char*, PtrMethod*, ltstr> theMap;
    >
    > protected:
    > Factory();
    >
    > ~Factory();
    >
    > Object * method1(std::vector<std::string>);
    > Object * method2(std::vector<std::string>);
    >
    > public:
    > Object *
    > getObject(std::string,std::vector<std::string>);
    >
    > };
    >
    > FACTORY_CPP
    >
    > Factory::Factory()
    > {
    > map["method1"] = &method1;
    > map["method2"] = &method2;
    >
    > }
    >
    > Object * Factory::getObject(string label,vector<string> paramaters)
    > {
    > PtrMethod method = theMap[label];
    > Object * object = (*method)(parameters); <- crash here.
    > return object;
    >
    > }
    >
    > ==================================================
    >
    > has somebody an idea? why does it crash?


    Who knows? Have you tried using a "debugger"? Read up on those.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 13, 2006
    #3
  4. Manuel

    mlimber Guest

    mlimber wrote:
    > Manuel wrote:
    > > hi,
    > >
    > > In the past I made the question "how to implement a simple class
    > > forname". I made this finally and it compiled well. but now when i
    > > execute the program, it crash with a sigsegv.
    > >
    > > The code is this:
    > >
    > > FACTORY_H
    > >
    > > typedef Object * (*PtrMethod)(std::vector<std::string>);
    > >
    > > class Factory
    > > {
    > > private:
    > > map<const char*, PtrMethod*, ltstr> theMap;
    > >
    > > protected:
    > > Factory();
    > >
    > > ~Factory();
    > >
    > > Object * method1(std::vector<std::string>);
    > > Object * method2(std::vector<std::string>);
    > >
    > > public:
    > > Object *
    > > getObject(std::string,std::vector<std::string>);
    > >
    > > };
    > >
    > > FACTORY_CPP
    > >
    > > Factory::Factory()
    > > {
    > > map["method1"] = &method1;
    > > map["method2"] = &method2;
    > >
    > > }
    > >
    > > Object * Factory::getObject(string label,vector<string> paramaters)
    > > {
    > > PtrMethod method = theMap[label];
    > > Object * object = (*method)(parameters); <- crash here.
    > > return object;
    > >
    > > }
    > >
    > > ==================================================
    > >
    > > has somebody an idea? why does it crash?

    >
    > Yes. It's because you're using map<>::eek:perator[]() to look-up the
    > value, and then you dereference the pointer without checking for null.
    > As you'll note in footnote 3 of SGI's description of the STL
    > (http://www.sgi.com/tech/stl/Map.html#3), if the key in question is not
    > found in the map, that operator does an insert, initializing the
    > corresponding value to its default (in this case, a null pointer).
    > That's generally not what you want.
    >
    > What you should be doing is calling std::map<>::find() to do your
    > lookup, and then make sure the value was found:
    >
    > std::auto_ptr<Object> Factory::getObject(
    > const string& label,
    > const vector<string>& paramaters)
    > {
    > typedef map<const char*, PtrMethod*, ltstr> MyMap;
    > const MyMap::const_iterator iter = theMap.find( label );
    > if( iter == theMap.end() )
    > {
    > return std::auto_ptr<Object>( 0 );
    > }
    >
    > const PtrMethod method = iter->second;
    > return std::auto_ptr<Object>( (*method)(parameters) );
    > }
    >
    > Note also that I changed the return type to std::auto_ptr so that the
    > caller knows it is responsible to cleanup that pointer, and I changed
    > the function parameters to const references to avoid unnecessary and
    > possibly expensive copies. You should do likewise in your member
    > functions above.
    >
    > Cheers! --M


    On second thought, your code has more problems than that.

    First, your map's value type is PtrMethod*, but PtrMethod is already a
    pointer type. Lose the extra star. Second, PtrMethod can only accept
    free-standing or static member functions, so you can't assign
    Factory::method1 or Factory::method2 to an object of type PtrMethod.
    There are various other sytax and typing errors, too. See the
    guidelines for posting code here
    (http://parashift.com/c -faq-lite/how-to-post.html#faq-5.8).

    Also, check out the Factory class provided by Loki
    (http://sourceforge.net/projects/loki-lib/), the library that is
    described in _Modern C++ Design_ by Alexandrescu. It's ready out of the
    box.

    Cheers! --M
     
    mlimber, Sep 13, 2006
    #4
  5. Manuel

    Manuel Guest

    mlimber ha escrito:

    > mlimber wrote:
    > > Manuel wrote:
    > > > hi,
    > > >
    > > > In the past I made the question "how to implement a simple class
    > > > forname". I made this finally and it compiled well. but now when i
    > > > execute the program, it crash with a sigsegv.
    > > >
    > > > The code is this:
    > > >
    > > > FACTORY_H
    > > >
    > > > typedef Object * (*PtrMethod)(std::vector<std::string>);
    > > >
    > > > class Factory
    > > > {
    > > > private:
    > > > map<const char*, PtrMethod*, ltstr> theMap;
    > > >
    > > > protected:
    > > > Factory();
    > > >
    > > > ~Factory();
    > > >
    > > > Object * method1(std::vector<std::string>);
    > > > Object * method2(std::vector<std::string>);
    > > >
    > > > public:
    > > > Object *
    > > > getObject(std::string,std::vector<std::string>);
    > > >
    > > > };
    > > >
    > > > FACTORY_CPP
    > > >
    > > > Factory::Factory()
    > > > {
    > > > map["method1"] = &method1;
    > > > map["method2"] = &method2;
    > > >
    > > > }
    > > >
    > > > Object * Factory::getObject(string label,vector<string> paramaters)
    > > > {
    > > > PtrMethod method = theMap[label];
    > > > Object * object = (*method)(parameters); <- crash here.
    > > > return object;
    > > >
    > > > }
    > > >
    > > > ==================================================
    > > >
    > > > has somebody an idea? why does it crash?

    > >
    > > Yes. It's because you're using map<>::eek:perator[]() to look-up the
    > > value, and then you dereference the pointer without checking for null.
    > > As you'll note in footnote 3 of SGI's description of the STL
    > > (http://www.sgi.com/tech/stl/Map.html#3), if the key in question is not
    > > found in the map, that operator does an insert, initializing the
    > > corresponding value to its default (in this case, a null pointer).
    > > That's generally not what you want.
    > >
    > > What you should be doing is calling std::map<>::find() to do your
    > > lookup, and then make sure the value was found:
    > >
    > > std::auto_ptr<Object> Factory::getObject(
    > > const string& label,
    > > const vector<string>& paramaters)
    > > {
    > > typedef map<const char*, PtrMethod*, ltstr> MyMap;
    > > const MyMap::const_iterator iter = theMap.find( label );
    > > if( iter == theMap.end() )
    > > {
    > > return std::auto_ptr<Object>( 0 );
    > > }
    > >
    > > const PtrMethod method = iter->second;
    > > return std::auto_ptr<Object>( (*method)(parameters) );
    > > }
    > >
    > > Note also that I changed the return type to std::auto_ptr so that the
    > > caller knows it is responsible to cleanup that pointer, and I changed
    > > the function parameters to const references to avoid unnecessary and
    > > possibly expensive copies. You should do likewise in your member
    > > functions above.
    > >
    > > Cheers! --M

    >
    > On second thought, your code has more problems than that.
    >
    > First, your map's value type is PtrMethod*, but PtrMethod is already a
    > pointer type. Lose the extra star. Second, PtrMethod can only accept
    > free-standing or static member functions, so you can't assign
    > Factory::method1 or Factory::method2 to an object of type PtrMethod.
    > There are various other sytax and typing errors, too. See the
    > guidelines for posting code here
    > (http://parashift.com/c -faq-lite/how-to-post.html#faq-5.8).
    >
    > Also, check out the Factory class provided by Loki
    > (http://sourceforge.net/projects/loki-lib/), the library that is
    > described in _Modern C++ Design_ by Alexandrescu. It's ready out of the
    > box.
    >
    > Cheers! --M


    Excuse me, mlimber. This code is a modify original code because that is
    in spanish and when i copy i had some mistakes.

    In the original code, de methods are statics and the map's value type
    is PtrMethod.
    I tried your code and it is worked correctly.
    Thank you very much.
     
    Manuel, Sep 13, 2006
    #5
  6. Manuel

    Manuel Guest

    Victor Bazarov ha escrito:

    > Manuel wrote:
    > > In the past I made the question "how to implement a simple class
    > > forname". I made this finally and it compiled well. but now when i
    > > execute the program,

    >
    > I don't think your code below is a complete C++ program. You might
    > want to consider posting the whole thing before asking for help with
    > "your program".
    >
    > > it crash with a sigsegv.
    > >
    > > The code is this:
    > >
    > > FACTORY_H
    > >
    > > typedef Object * (*PtrMethod)(std::vector<std::string>);
    > >
    > > class Factory
    > > {
    > > private:
    > > map<const char*, PtrMethod*, ltstr> theMap;
    > >
    > > protected:
    > > Factory();
    > >
    > > ~Factory();
    > >
    > > Object * method1(std::vector<std::string>);
    > > Object * method2(std::vector<std::string>);
    > >
    > > public:
    > > Object *
    > > getObject(std::string,std::vector<std::string>);
    > >
    > > };
    > >
    > > FACTORY_CPP
    > >
    > > Factory::Factory()
    > > {
    > > map["method1"] = &method1;
    > > map["method2"] = &method2;
    > >
    > > }
    > >
    > > Object * Factory::getObject(string label,vector<string> paramaters)
    > > {
    > > PtrMethod method = theMap[label];
    > > Object * object = (*method)(parameters); <- crash here.
    > > return object;
    > >
    > > }
    > >
    > > ==================================================
    > >
    > > has somebody an idea? why does it crash?

    >
    > Who knows? Have you tried using a "debugger"? Read up on those.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    I already know it. for that reason it knew where it had failed...

    that code I did it with your aid and I think that is sufficient in
    order to explain what desire to do since it has been seen.

    Of all ways, thank you very much

    bye,
    Manuel
     
    Manuel, Sep 13, 2006
    #6
  7. Manuel wrote:

    > hi,
    >
    > In the past I made the question "how to implement a simple class
    > forname". I made this finally and it compiled well. but now when i
    > execute the program, it crash with a sigsegv.
    >
    > The code is this:
    >
    > FACTORY_H
    >
    > typedef Object * (*PtrMethod)(std::vector<std::string>);
    >
    > class Factory
    > {
    > private:
    > map<const char*, PtrMethod*, ltstr> theMap;
    >
    > protected:
    > Factory();
    >
    > ~Factory();
    >
    > Object * method1(std::vector<std::string>);
    > Object * method2(std::vector<std::string>);
    >
    > public:
    > Object *
    > getObject(std::string,std::vector<std::string>);
    >
    > };
    >
    > FACTORY_CPP
    >
    > Factory::Factory()
    > {
    > map["method1"] = &method1;
    > map["method2"] = &method2;
    >
    > }
    >
    > Object * Factory::getObject(string label,vector<string> paramaters)
    > {

    //PtrMethod method = theMap[label];
    PtrMethod *method = theMap[label];
    > Object * object = (*method)(parameters); <- crash here.
    > return object;
    >
    > }
    >
    > ==================================================
    >
    > has somebody an idea? why does it crash?


    Konstantin
     
    Konstantin Miller, Sep 13, 2006
    #7
  8. Manuel

    Manuel Guest

    mlimber ha escrito:

    > mlimber wrote:
    > > Manuel wrote:
    > > > hi,
    > > >
    > > > In the past I made the question "how to implement a simple class
    > > > forname". I made this finally and it compiled well. but now when i
    > > > execute the program, it crash with a sigsegv.
    > > >
    > > > The code is this:
    > > >
    > > > FACTORY_H
    > > >
    > > > typedef Object * (*PtrMethod)(std::vector<std::string>);
    > > >
    > > > class Factory
    > > > {
    > > > private:
    > > > map<const char*, PtrMethod*, ltstr> theMap;
    > > >
    > > > protected:
    > > > Factory();
    > > >
    > > > ~Factory();
    > > >
    > > > Object * method1(std::vector<std::string>);
    > > > Object * method2(std::vector<std::string>);
    > > >
    > > > public:
    > > > Object *
    > > > getObject(std::string,std::vector<std::string>);
    > > >
    > > > };
    > > >
    > > > FACTORY_CPP
    > > >
    > > > Factory::Factory()
    > > > {
    > > > map["method1"] = &method1;
    > > > map["method2"] = &method2;
    > > >
    > > > }
    > > >
    > > > Object * Factory::getObject(string label,vector<string> paramaters)
    > > > {
    > > > PtrMethod method = theMap[label];
    > > > Object * object = (*method)(parameters); <- crash here.
    > > > return object;
    > > >
    > > > }
    > > >
    > > > ==================================================
    > > >
    > > > has somebody an idea? why does it crash?

    > >
    > > Yes. It's because you're using map<>::eek:perator[]() to look-up the
    > > value, and then you dereference the pointer without checking for null.
    > > As you'll note in footnote 3 of SGI's description of the STL
    > > (http://www.sgi.com/tech/stl/Map.html#3), if the key in question is not
    > > found in the map, that operator does an insert, initializing the
    > > corresponding value to its default (in this case, a null pointer).
    > > That's generally not what you want.
    > >
    > > What you should be doing is calling std::map<>::find() to do your
    > > lookup, and then make sure the value was found:
    > >
    > > std::auto_ptr<Object> Factory::getObject(
    > > const string& label,
    > > const vector<string>& paramaters)
    > > {
    > > typedef map<const char*, PtrMethod*, ltstr> MyMap;
    > > const MyMap::const_iterator iter = theMap.find( label );
    > > if( iter == theMap.end() )
    > > {
    > > return std::auto_ptr<Object>( 0 );
    > > }
    > >
    > > const PtrMethod method = iter->second;
    > > return std::auto_ptr<Object>( (*method)(parameters) );
    > > }
    > >
    > > Note also that I changed the return type to std::auto_ptr so that the
    > > caller knows it is responsible to cleanup that pointer, and I changed
    > > the function parameters to const references to avoid unnecessary and
    > > possibly expensive copies. You should do likewise in your member
    > > functions above.
    > >
    > > Cheers! --M

    >
    > On second thought, your code has more problems than that.
    >
    > First, your map's value type is PtrMethod*, but PtrMethod is already a
    > pointer type. Lose the extra star. Second, PtrMethod can only accept
    > free-standing or static member functions, so you can't assign
    > Factory::method1 or Factory::method2 to an object of type PtrMethod.
    > There are various other sytax and typing errors, too. See the
    > guidelines for posting code here
    > (http://parashift.com/c -faq-lite/how-to-post.html#faq-5.8).
    >
    > Also, check out the Factory class provided by Loki
    > (http://sourceforge.net/projects/loki-lib/), the library that is
    > described in _Modern C++ Design_ by Alexandrescu. It's ready out of the
    > box.
    >
    > Cheers! --M


    Hello again.

    The code work but i am testing and i found a new bug.
    well, the code work when I defined the label in the function:

    std::auto_ptr<Object> Factory::getObject(const vector<string>&
    paramaters)
    {
    const char * label = "label";
    typedef map<const char*, PtrMethod*, ltstr> MyMap;
    const MyMap::const_iterator iter = theMap.find( label );
    if( iter == theMap.end() )
    {
    return std::auto_ptr<Object>( 0 );
    }
    but when i try like i need:

    this code find the label in the map.

    But this other code where i use a string that convert in const char *
    does not find nothing

    std::auto_ptr<Object> Factory::getObject(const string& label,const
    vector<string>& paramaters)
    {
    typedef map<const char*, PtrMethod*, ltstr> MyMap;
    const MyMap::const_iterator iter = theMap.find( label.c_str() );
    if( iter == theMap.end() )
    {
    return std::auto_ptr<Object>( 0 );
    }

    The method "find" does not find nothing. why?

    I compare two streams with strcmp and it return 0 so they are equals.
    I do not understand because it does not work.
     
    Manuel, Sep 14, 2006
    #8
  9. Manuel schrieb:
    [...]
    > But this other code where i use a string that convert in const char *
    > does not find nothing


    When it does not find nothing, then it finds something, doesn't it?

    > std::auto_ptr<Object> Factory::getObject(const string& label,const
    > vector<string>& paramaters)
    > {
    > typedef map<const char*, PtrMethod*, ltstr> MyMap;
    > const MyMap::const_iterator iter = theMap.find( label.c_str() );
    > if( iter == theMap.end() )
    > {
    > return std::auto_ptr<Object>( 0 );
    > }
    >
    > The method "find" does not find nothing. why?
    >
    > I compare two streams with strcmp and it return 0 so they are equals.
    > I do not understand because it does not work.


    You are comparing wrong. Show us your code. Show us your ltstr-Functor.
    Post a minimal example of code, that has this problem.

    And use std::map<string, ...> instead of std::map<const char*, ...> if you
    don't have a good reason not to do so.

    --
    Thomas
    http://www.netmeister.org/news/learn2quote.html
     
    Thomas J. Gritzan, Sep 14, 2006
    #9
  10. Manuel

    mlimber Guest

    Thomas J. Gritzan wrote:
    > Manuel schrieb:
    > [...]
    > > But this other code where i use a string that convert in const char *
    > > does not find nothing

    >
    > When it does not find nothing, then it finds something, doesn't it?
    >
    > > std::auto_ptr<Object> Factory::getObject(const string& label,const
    > > vector<string>& paramaters)
    > > {
    > > typedef map<const char*, PtrMethod*, ltstr> MyMap;
    > > const MyMap::const_iterator iter = theMap.find( label.c_str() );
    > > if( iter == theMap.end() )
    > > {
    > > return std::auto_ptr<Object>( 0 );
    > > }
    > >
    > > The method "find" does not find nothing. why?
    > >
    > > I compare two streams with strcmp and it return 0 so they are equals.
    > > I do not understand because it does not work.

    >
    > You are comparing wrong. Show us your code. Show us your ltstr-Functor.
    > Post a minimal example of code, that has this problem.
    >
    > And use std::map<string, ...> instead of std::map<const char*, ...> if you
    > don't have a good reason not to do so.


    Thomas is right. Follow the code posting guideline I cited earlier, and
    post a minimal but complete sample (i.e., one that we can cut and paste
    into our editors unchanged) that demonstrates your problem.

    Cheers! --M
     
    mlimber, Sep 14, 2006
    #10
  11. Manuel wrote:
    > > > typedef map<const char*, PtrMethod*, ltstr> MyMap;


    You want to think about this const char * business. Consider this:

    std::string s1( "A string" ), s2( "A string" );
    const char *ps1( "A string" ), *ps2( "A string" );

    What happens depends somewhat on your compiler, but

    s1 == s2

    Will return true because the std::string class compares the content of
    the two strings. Normally you would expect (see caveat at end though):

    ps1 != ps2

    Because the memory locations that hold the two strings will be
    different. Comparing the pointers of character arrays compares the
    memory locations and NOT the strings themselves.

    The one time that this may be different is if your compiler supports
    (and you have the option turned on) common string coalescing. This
    would then store a single version of "A string" in the data area of the
    compiled program and all four memory pointers would point to the same
    thing. But even with this it would be no guarantee that the
    compiler/linker would be able to do it.

    As you're writing C++ you should prefer std::string over const char *
    unless you know exactly what you're doing and why you are doing it.
    You'll get less nasty surprises that way.


    K
     
    =?iso-8859-1?q?Kirit_S=E6lensminde?=, Sep 14, 2006
    #11
  12. Manuel

    Manuel Guest

    Kirit Sælensminde wrote:
    > Manuel wrote:
    > > > > typedef map<const char*, PtrMethod*, ltstr> MyMap;

    >
    > You want to think about this const char * business. Consider this:
    >
    > std::string s1( "A string" ), s2( "A string" );
    > const char *ps1( "A string" ), *ps2( "A string" );
    >
    > What happens depends somewhat on your compiler, but
    >
    > s1 == s2
    >
    > Will return true because the std::string class compares the content of
    > the two strings. Normally you would expect (see caveat at end though):
    >
    > ps1 != ps2
    >
    > Because the memory locations that hold the two strings will be
    > different. Comparing the pointers of character arrays compares the
    > memory locations and NOT the strings themselves.
    >
    > The one time that this may be different is if your compiler supports
    > (and you have the option turned on) common string coalescing. This
    > would then store a single version of "A string" in the data area of the
    > compiled program and all four memory pointers would point to the same
    > thing. But even with this it would be no guarantee that the
    > compiler/linker would be able to do it.
    >
    > As you're writing C++ you should prefer std::string over const char *
    > unless you know exactly what you're doing and why you are doing it.
    > You'll get less nasty surprises that way.
    >
    >
    > K


    Hi,

    Excuse me by not have posted all the code.

    I followed your indications and i defined the map with the strings.
    Then the code would be thus:

    #The constructor:
    FabricaDeEnergia::FabricaDeEnergia()
    {
    mapaEnergias["EnergiaInterna"] = &crearEnergiaInterna;
    mapaEnergias["EnergiaBorde"] = &crearEnergiaBorde;
    mapaEnergias["EnergiaDistanciaNormal"] = &crearEnergiaDistanciaNormal;
    mapaEnergias["EnergiaMapaDistancia"] = &crearEnergiaMapaDistancia;
    mapaEnergias["EnergiaPresion"] = &crearEnergiaPresion;
    }

    #The functions.
    typedef struct
    {
    bool operator()(std::string s1, std::string s2) const
    {
    return (s1 == s2);
    }
    }ltstr;

    auto_ptr<Energia> FabricaDeEnergia::getEnergia(const vector<string>&
    atributos)
    {
    typedef map<string, PtrMetodoEnergia, ltstr> miMapa;
    const miMapa::const_iterator iter = mapaEnergias.find(
    "EnergiaInterna");
    if( iter == mapaEnergias.end() )
    {
    return auto_ptr<Energia>( 0 );
    }

    const PtrMetodoEnergia metodo = iter->second;
    return auto_ptr<Energia>( (*metodo)(atributos) );
    }

    I test the code with a debugger and when the mapaEnergias.find is
    execute this use corretly the function ltstr. In spite of this, it
    continues giving back the end of the map

    I don't understand that it's happening :(
     
    Manuel, Sep 14, 2006
    #12
  13. Manuel

    Manuel Guest

    Manuel wrote:
    > Kirit Sælensminde wrote:
    > > Manuel wrote:
    > > > > > typedef map<const char*, PtrMethod*, ltstr> MyMap;

    > >
    > > You want to think about this const char * business. Consider this:
    > >
    > > std::string s1( "A string" ), s2( "A string" );
    > > const char *ps1( "A string" ), *ps2( "A string" );
    > >
    > > What happens depends somewhat on your compiler, but
    > >
    > > s1 == s2
    > >
    > > Will return true because the std::string class compares the content of
    > > the two strings. Normally you would expect (see caveat at end though):
    > >
    > > ps1 != ps2
    > >
    > > Because the memory locations that hold the two strings will be
    > > different. Comparing the pointers of character arrays compares the
    > > memory locations and NOT the strings themselves.
    > >
    > > The one time that this may be different is if your compiler supports
    > > (and you have the option turned on) common string coalescing. This
    > > would then store a single version of "A string" in the data area of the
    > > compiled program and all four memory pointers would point to the same
    > > thing. But even with this it would be no guarantee that the
    > > compiler/linker would be able to do it.
    > >
    > > As you're writing C++ you should prefer std::string over const char *
    > > unless you know exactly what you're doing and why you are doing it.
    > > You'll get less nasty surprises that way.
    > >
    > >
    > > K

    >
    > Hi,
    >
    > Excuse me by not have posted all the code.
    >
    > I followed your indications and i defined the map with the strings.
    > Then the code would be thus:
    >
    > #The constructor:
    > FabricaDeEnergia::FabricaDeEnergia()
    > {
    > mapaEnergias["EnergiaInterna"] = &crearEnergiaInterna;
    > mapaEnergias["EnergiaBorde"] = &crearEnergiaBorde;
    > mapaEnergias["EnergiaDistanciaNormal"] = &crearEnergiaDistanciaNormal;
    > mapaEnergias["EnergiaMapaDistancia"] = &crearEnergiaMapaDistancia;
    > mapaEnergias["EnergiaPresion"] = &crearEnergiaPresion;
    > }
    >
    > #The functions.
    > typedef struct
    > {
    > bool operator()(std::string s1, std::string s2) const
    > {
    > return (s1 == s2);
    > }
    > }ltstr;
    >
    > auto_ptr<Energia> FabricaDeEnergia::getEnergia(const vector<string>&
    > atributos)
    > {
    > typedef map<string, PtrMetodoEnergia, ltstr> miMapa;
    > const miMapa::const_iterator iter = mapaEnergias.find(
    > "EnergiaInterna");
    > if( iter == mapaEnergias.end() )
    > {
    > return auto_ptr<Energia>( 0 );
    > }
    >
    > const PtrMetodoEnergia metodo = iter->second;
    > return auto_ptr<Energia>( (*metodo)(atributos) );
    > }
    >
    > I test the code with a debugger and when the mapaEnergias.find is
    > execute this use corretly the function ltstr. In spite of this, it
    > continues giving back the end of the map
    >
    > I don't understand that it's happening :(


    well, i am surprise. I tried without ltstr and it worked fine.

    I follow without understanding nothing :'(
     
    Manuel, Sep 14, 2006
    #13
  14. Manuel schrieb:
    > #The functions.
    > typedef struct
    > {
    > bool operator()(std::string s1, std::string s2) const


    bool operator()(const std::string& s1, const std::string& s2) const

    > {
    > return (s1 == s2);


    return s1 < s2;

    > }
    > }ltstr;
    >
    > auto_ptr<Energia> FabricaDeEnergia::getEnergia(const vector<string>&
    > atributos)
    > {
    > typedef map<string, PtrMetodoEnergia, ltstr> miMapa;

    [...]
    >
    > I test the code with a debugger and when the mapaEnergias.find is
    > execute this use corretly the function ltstr. In spite of this, it
    > continues giving back the end of the map
    >
    > I don't understand that it's happening :(


    As I said, you were compareing wrong. The 3rd template parameter of
    std::map must not be an equality comparator. The default is std::less,
    which uses operator<.

    --
    Thomas
    http://www.netmeister.org/news/learn2quote.html
     
    Thomas J. Gritzan, Sep 14, 2006
    #14
  15. Manuel

    Manuel Guest

    Thomas J. Gritzan wrote:
    > Manuel schrieb:
    > > #The functions.
    > > typedef struct
    > > {
    > > bool operator()(std::string s1, std::string s2) const

    >
    > bool operator()(const std::string& s1, const std::string& s2) const
    >
    > > {
    > > return (s1 == s2);

    >
    > return s1 < s2;
    >
    > > }
    > > }ltstr;
    > >
    > > auto_ptr<Energia> FabricaDeEnergia::getEnergia(const vector<string>&
    > > atributos)
    > > {
    > > typedef map<string, PtrMetodoEnergia, ltstr> miMapa;

    > [...]
    > >
    > > I test the code with a debugger and when the mapaEnergias.find is
    > > execute this use corretly the function ltstr. In spite of this, it
    > > continues giving back the end of the map
    > >
    > > I don't understand that it's happening :(

    >
    > As I said, you were compareing wrong. The 3rd template parameter of
    > std::map must not be an equality comparator. The default is std::less,
    > which uses operator<.
    >
    > --
    > Thomas
    > http://www.netmeister.org/news/learn2quote.html


    oh, ok. But now it is rule without the 3rd template parameter. would
    have to also use it?

    Thanks
     
    Manuel, Sep 15, 2006
    #15
  16. Manuel wrote:
    > Thomas J. Gritzan wrote:
    > > Manuel schrieb:
    > > >
    > > > I don't understand that it's happening :(

    > >
    > > As I said, you were compareing wrong. The 3rd template parameter of
    > > std::map must not be an equality comparator. The default is std::less,
    > > which uses operator<.

    > oh, ok. But now it is rule without the 3rd template parameter. would
    > have to also use it?
    >


    All of this use of const char * is just confusing you. I think some
    people tried to help by giving you some code that would let you compare
    the const char *, but it's simpler to just ignore that complication now
    and concentrate on getting things to work with std::string instead. The
    default third template argument for std::map is fine for pretty much
    all uses of the class. When you need to change it you will know. I must
    have used std::map hundreds (if not a thousand) places and only changed
    that parameter less than 10 times.

    Some times I have changed it to std::greater because I wanted to go
    through maps in the other order (I know I can also use rbegin etc.) and
    there have been very few times I've written my own.

    I didn't examine it closely, but it looked like you might be taking the
    address of some (stack/global) instances and putting them in a map that
    took std::auto_ptr. This is a really bad idea!

    const PtrMetodoEnergia metodo = iter->second;
    return auto_ptr<Energia>( (*metodo)(atributos) );

    This sort of code is pretty unlikely to be the right thing to do.
    Personally I never use std::auto_ptr - I prefer the boost smart
    pointers. std::auto_ptr has a quirks that you need to fully understand
    to use it succesfully. It looks to me like you would be better off with
    boost::shared_ptr as it is much harder to abuse.


    K
     
    =?iso-8859-1?q?Kirit_S=E6lensminde?=, Sep 15, 2006
    #16
  17. Manuel

    Manuel Guest

    Kirit Sælensminde ha escrito:

    > Manuel wrote:
    > > Thomas J. Gritzan wrote:
    > > > Manuel schrieb:
    > > > >
    > > > > I don't understand that it's happening :(
    > > >
    > > > As I said, you were compareing wrong. The 3rd template parameter of
    > > > std::map must not be an equality comparator. The default is std::less,
    > > > which uses operator<.

    > > oh, ok. But now it is rule without the 3rd template parameter. would
    > > have to also use it?
    > >

    >
    > All of this use of const char * is just confusing you. I think some
    > people tried to help by giving you some code that would let you compare
    > the const char *, but it's simpler to just ignore that complication now
    > and concentrate on getting things to work with std::string instead. The
    > default third template argument for std::map is fine for pretty much
    > all uses of the class. When you need to change it you will know. I must
    > have used std::map hundreds (if not a thousand) places and only changed
    > that parameter less than 10 times.
    >
    > Some times I have changed it to std::greater because I wanted to go
    > through maps in the other order (I know I can also use rbegin etc.) and
    > there have been very few times I've written my own.
    >
    > I didn't examine it closely, but it looked like you might be taking the
    > address of some (stack/global) instances and putting them in a map that
    > took std::auto_ptr. This is a really bad idea!
    >
    > const PtrMetodoEnergia metodo = iter->second;
    > return auto_ptr<Energia>( (*metodo)(atributos) );
    >
    > This sort of code is pretty unlikely to be the right thing to do.
    > Personally I never use std::auto_ptr - I prefer the boost smart
    > pointers. std::auto_ptr has a quirks that you need to fully understand
    > to use it succesfully. It looks to me like you would be better off with
    > boost::shared_ptr as it is much harder to abuse.
    >
    >
    > K


    now I understood it, thank you.

    I will read some documents about shared_ptr and auto_ptr because yet i
    don't understand very well.

    bye,
    M
     
    Manuel, Sep 15, 2006
    #17
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. iksrazal

    Re: Class.forname() vs clone()

    iksrazal, Jun 27, 2003, in forum: Java
    Replies:
    0
    Views:
    1,626
    iksrazal
    Jun 27, 2003
  2. Ahmed Moustafa

    performance of Class.forname()?

    Ahmed Moustafa, Jul 20, 2003, in forum: Java
    Replies:
    14
    Views:
    6,077
    Chris Smith
    Jul 29, 2003
  3. H.MuthuKumaraRajan

    .class and Class.forName

    H.MuthuKumaraRajan, Nov 6, 2003, in forum: Java
    Replies:
    11
    Views:
    1,785
    H.MuthuKumaraRajan
    Nov 7, 2003
  4. cyril
    Replies:
    2
    Views:
    3,946
    cyril
    Aug 25, 2004
  5. Madni
    Replies:
    1
    Views:
    5,931
Loading...

Share This Page