Why can't the linker find the definitions?

Discussion in 'C++' started by William Payne, Sep 22, 2004.

  1. Hello, I am toying with a simple string class I wrote quite some time ago. I
    noticed that if I try to use operator == or != I get undefiend references,
    but I dont see why. In my class declaration I have:
    bool operator==(const String& rhs) const;
    bool operator!=(const String& rhs) const;
    (In the public section.)

    And in the implementation file of my little string class, I have:
    inline bool
    String::eek:perator==(const String& rhs) const
    {
    return std::strcmp(m_internal_string, rhs.m_internal_string);
    }

    inline bool
    String::eek:perator!=(const String& rhs) const
    {
    return !((*this) == rhs);
    }

    The code that triggers these undefined references is simply:
    if(str == s2)
    {
    cout << "s2 == str" << endl;
    }
    else
    {
    cout << "s2 != str" << endl;
    }

    if(str != s2)
    {
    cout << "s2 != str" << endl;
    }
    else
    {
    cout << "s2 == str" << endl;
    }

    where str and s2 is of type String (my string class).

    And one more thing, if the compiler rejects:
    String foo("bar");
    foo[1] = c; // Doesn't like this line!

    what am I missing?

    Thanks for any replies!

    / WP
    William Payne, Sep 22, 2004
    #1
    1. Advertising

  2. William Payne

    David Hilsee Guest

    "William Payne" <> wrote in message
    news:ciqbqe$g7a$...
    > Hello, I am toying with a simple string class I wrote quite some time ago.

    I
    > noticed that if I try to use operator == or != I get undefiend references,
    > but I dont see why. In my class declaration I have:
    > bool operator==(const String& rhs) const;
    > bool operator!=(const String& rhs) const;
    > (In the public section.)
    >
    > And in the implementation file of my little string class, I have:
    > inline bool
    > String::eek:perator==(const String& rhs) const
    > {
    > return std::strcmp(m_internal_string, rhs.m_internal_string);
    > }
    >
    > inline bool
    > String::eek:perator!=(const String& rhs) const
    > {
    > return !((*this) == rhs);
    > }

    <snip>

    Functions that are declared inline have internal linkage and should be
    defined in the header. Move these to the header file. If you need a
    helpful reminder as to why, just remember that "inline" means that the
    programmer wishes to have the code "pasted" into the caller's source, so the
    compiler needs to "see" it when compiling other implementation files.

    --
    David Hilsee
    David Hilsee, Sep 22, 2004
    #2
    1. Advertising

  3. "William Payne" <> wrote in message
    news:ciqbqe$g7a$...
    > Hello, I am toying with a simple string class I wrote quite some time ago.
    > I noticed that if I try to use operator == or != I get undefiend
    > references, but I dont see why. In my class declaration I have:
    > bool operator==(const String& rhs) const;
    > bool operator!=(const String& rhs) const;
    > (In the public section.)
    >
    > And in the implementation file of my little string class, I have:
    > inline bool
    > String::eek:perator==(const String& rhs) const
    > {
    > return std::strcmp(m_internal_string, rhs.m_internal_string);
    > }
    >
    > inline bool
    > String::eek:perator!=(const String& rhs) const
    > {
    > return !((*this) == rhs);
    > }


    Why are they declared inline if they are in the implementation file?

    inline functions go in the header file, non-inline functions go in the
    implementation file.

    [snip]

    >
    > And one more thing, if the compiler rejects:
    > String foo("bar");
    > foo[1] = c; // Doesn't like this line!
    >


    Hard to say without seeing the rest of the code. What is c declared as? What
    is String::eek:perator[] declared as?

    john
    John Harrison, Sep 22, 2004
    #3
  4. "John Harrison" <> wrote in message
    news:...
    >
    > "William Payne" <> wrote in message
    > news:ciqbqe$g7a$...
    >> Hello, I am toying with a simple string class I wrote quite some time
    >> ago. I noticed that if I try to use operator == or != I get undefiend
    >> references, but I dont see why. In my class declaration I have:
    >> bool operator==(const String& rhs) const;
    >> bool operator!=(const String& rhs) const;
    >> (In the public section.)
    >>
    >> And in the implementation file of my little string class, I have:
    >> inline bool
    >> String::eek:perator==(const String& rhs) const
    >> {
    >> return std::strcmp(m_internal_string, rhs.m_internal_string);
    >> }
    >>
    >> inline bool
    >> String::eek:perator!=(const String& rhs) const
    >> {
    >> return !((*this) == rhs);
    >> }

    >
    > Why are they declared inline if they are in the implementation file?
    >
    > inline functions go in the header file, non-inline functions go in the
    > implementation file.
    >
    > [snip]
    >
    >>
    >> And one more thing, if the compiler rejects:
    >> String foo("bar");
    >> foo[1] = c; // Doesn't like this line!
    >>

    >
    > Hard to say without seeing the rest of the code. What is c declared as?
    > What is String::eek:perator[] declared as?
    >
    > john
    >
    >


    Thanks for the quick reply, both of you. I just noticed that it was indeed
    my use of inline in the .cpp-file that was the culprit of the linking
    errors. For some reason I thought that any function defined in the header
    file would be inlined automatically and that I could use the keyword inline
    to request functions defined in the implementation file (cpp-file) to be
    inlined as well, provided they were short enough. So if I want to request a
    function to be inlined, it must be defined in the header? Inside the class
    declaration itself or can it be outside (but still in the header)?

    c is of type char, sorry, should've posted that.
    and operator[] is declared as:
    char operator[](std::size_t index) const;

    I need two versions, one non-const?

    / WP
    William Payne, Sep 22, 2004
    #4
  5. William Payne

    David Hilsee Guest

    "William Payne" <> wrote in message
    news:ciqd2r$gkd$...
    >
    > "John Harrison" <> wrote in message
    > news:...
    > >
    > > "William Payne" <> wrote in message
    > > news:ciqbqe$g7a$...
    > >> Hello, I am toying with a simple string class I wrote quite some time
    > >> ago. I noticed that if I try to use operator == or != I get undefiend
    > >> references, but I dont see why. In my class declaration I have:
    > >> bool operator==(const String& rhs) const;
    > >> bool operator!=(const String& rhs) const;
    > >> (In the public section.)
    > >>
    > >> And in the implementation file of my little string class, I have:
    > >> inline bool
    > >> String::eek:perator==(const String& rhs) const
    > >> {
    > >> return std::strcmp(m_internal_string, rhs.m_internal_string);
    > >> }
    > >>
    > >> inline bool
    > >> String::eek:perator!=(const String& rhs) const
    > >> {
    > >> return !((*this) == rhs);
    > >> }

    > >
    > > Why are they declared inline if they are in the implementation file?
    > >
    > > inline functions go in the header file, non-inline functions go in the
    > > implementation file.
    > >
    > > [snip]
    > >
    > >>
    > >> And one more thing, if the compiler rejects:
    > >> String foo("bar");
    > >> foo[1] = c; // Doesn't like this line!
    > >>

    > >
    > > Hard to say without seeing the rest of the code. What is c declared as?
    > > What is String::eek:perator[] declared as?
    > >
    > > john
    > >
    > >

    >
    > Thanks for the quick reply, both of you. I just noticed that it was indeed
    > my use of inline in the .cpp-file that was the culprit of the linking
    > errors. For some reason I thought that any function defined in the header
    > file would be inlined automatically and that I could use the keyword

    inline
    > to request functions defined in the implementation file (cpp-file) to be
    > inlined as well, provided they were short enough. So if I want to request

    a
    > function to be inlined, it must be defined in the header? Inside the class
    > declaration itself or can it be outside (but still in the header)?


    Member functions that are defined inside the class definition are implicitly
    inline, not those declared inside of a header file. If you wish to define
    an inline member function outside of the class definition (and use it in
    other translation units), then you need to use the inline keyword. If you
    have an inline member function that is only called in a single translation
    unit containing its definition (e.g. a private member function), then you
    could conceivably define it there, in an implementation (.cpp) file.
    ("Translation unit" essentially means "implementation file" + "included
    headers in that implementation file")

    > c is of type char, sorry, should've posted that.
    > and operator[] is declared as:
    > char operator[](std::size_t index) const;
    >
    > I need two versions, one non-const?


    Yes. Have it return a reference, or some object that can act as a proxy for
    the char.

    char& operator[](std::size_t index);

    --
    David Hilsee
    David Hilsee, Sep 22, 2004
    #5
  6. William Payne wrote:

    > For some reason, I thought that any function defined in the header file
    > would be inlined automatically


    And, depending upon the implementation, that may be just what happens.

    > and that I could use the keyword inline to request
    > functions defined in the implementation file (cpp-file) to be
    > inlined as well, provided they were short enough.


    Some compilers do look for function definitions
    in other translation units and inline them automatically.
    That' one reason why inline function definitions
    should be the same in *all* translation units.

    > So, if I want to request a
    > function to be inlined, it must be defined in the header?
    > Inside the class declaration itself?


    If you define the function inside the class definition,
    it is an inline function.

    > Or can it be outside (but still in the header)?


    You must *declare* the function in the class definition
    then use the 'inline' qualifier when you define the function
    outside of the class definition.
    Remember to define the inline function
    *before* you invoke it or it will be inline'd
    and your link editor may complain about "undefined references".
    E. Robert Tisdale, Sep 22, 2004
    #6
  7. William Payne

    Kid Guest

    "William Payne" <> wrote in message news:<ciqbqe$g7a$>...
    > Hello, I am toying with a simple string class I wrote quite some time ago. I
    > noticed that if I try to use operator == or != I get undefiend references,
    > but I dont see why. In my class declaration I have:
    > bool operator==(const String& rhs) const;
    > bool operator!=(const String& rhs) const;
    > (In the public section.)
    >
    > And in the implementation file of my little string class, I have:
    > inline bool
    > String::eek:perator==(const String& rhs) const
    > {
    > return std::strcmp(m_internal_string, rhs.m_internal_string);
    > }
    >
    > inline bool
    > String::eek:perator!=(const String& rhs) const
    > {
    > return !((*this) == rhs);
    > }
    >
    > The code that triggers these undefined references is simply:
    > if(str == s2)
    > {
    > cout << "s2 == str" << endl;
    > }
    > else
    > {
    > cout << "s2 != str" << endl;
    > }
    >
    > if(str != s2)
    > {
    > cout << "s2 != str" << endl;
    > }
    > else
    > {
    > cout << "s2 == str" << endl;
    > }
    >
    > where str and s2 is of type String (my string class).
    >
    > And one more thing, if the compiler rejects:
    > String foo("bar");
    > foo[1] = c; // Doesn't like this line!
    >
    > what am I missing?
    >
    > Thanks for any replies!
    >
    > / WP


    IIRC, strcmp doesn't reside in namespace std; that is, remove the
    std:: and you should be fine. Also, the correctness of foo[1] = c
    depends on the type of c, though I'll take a leap of faith and assume
    you meant foo[1] = 'c', in which case you'll need [] overlaoded to
    begin with. You do realise there is a std::string already written,
    right?
    Kid, Sep 22, 2004
    #7
  8. "Kid" <> wrote in message
    news:...
    > "William Payne" <> wrote in message
    > news:<ciqbqe$g7a$>...
    >> Hello, I am toying with a simple string class I wrote quite some time
    >> ago. I
    >> noticed that if I try to use operator == or != I get undefiend
    >> references,
    >> but I dont see why. In my class declaration I have:
    >> bool operator==(const String& rhs) const;
    >> bool operator!=(const String& rhs) const;
    >> (In the public section.)
    >>
    >> And in the implementation file of my little string class, I have:
    >> inline bool
    >> String::eek:perator==(const String& rhs) const
    >> {
    >> return std::strcmp(m_internal_string, rhs.m_internal_string);
    >> }
    >>
    >> inline bool
    >> String::eek:perator!=(const String& rhs) const
    >> {
    >> return !((*this) == rhs);
    >> }
    >>
    >> The code that triggers these undefined references is simply:
    >> if(str == s2)
    >> {
    >> cout << "s2 == str" << endl;
    >> }
    >> else
    >> {
    >> cout << "s2 != str" << endl;
    >> }
    >>
    >> if(str != s2)
    >> {
    >> cout << "s2 != str" << endl;
    >> }
    >> else
    >> {
    >> cout << "s2 == str" << endl;
    >> }
    >>
    >> where str and s2 is of type String (my string class).
    >>
    >> And one more thing, if the compiler rejects:
    >> String foo("bar");
    >> foo[1] = c; // Doesn't like this line!
    >>
    >> what am I missing?
    >>
    >> Thanks for any replies!
    >>
    >> / WP

    >
    > IIRC, strcmp doesn't reside in namespace std; that is, remove the
    > std:: and you should be fine.


    Then you should take a look at the standard C++ header <cstring>

    / WP
    William Payne, Sep 22, 2004
    #8
  9. William Payne

    Old Wolf Guest

    "William Payne" <> wrote:
    > >> Hello, I am toying with a simple string class I wrote quite
    > >> some time ago.
    > >>
    > >> And one more thing, if the compiler rejects:
    > >> String foo("bar");
    > >> foo[1] = c; // Doesn't like this line!
    > >>

    > c is of type char, sorry, should've posted that.
    > and operator[] is declared as:
    > char operator[](std::size_t index) const;


    If you return a char then how do you expect the original string to
    be modified? Clearly you need to return a reference into the
    actual storage of the string's contents.

    Unfortunately you have to have 2 member functions for this:
    char & operator[](int);
    char const & operator[](int) const;
    so that with const objects you get const references and with
    non-const strings you get a non-const reference which you
    can then modify. If you want to support volatile strings
    then you also have to add:
    char volatile & operator[](int) volatile;
    char const volatile & operator[](int) const volatile;
    It would be nice if there were some language feature
    to prevent all this repetition.
    Old Wolf, Sep 22, 2004
    #9
    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. Andrew

    Linker error multiple definitions

    Andrew, Nov 18, 2003, in forum: C Programming
    Replies:
    4
    Views:
    537
    Andrew
    Nov 19, 2003
  2. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    877
    Mark Rae
    Dec 21, 2006
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,805
    Smokey Grindel
    Dec 2, 2006
  4. Replies:
    4
    Views:
    398
  5. Jeremy Banks
    Replies:
    12
    Views:
    434
    Steven D'Aprano
    Apr 24, 2009
Loading...

Share This Page