简体   繁体   中英

c++ undefined reference to member function defined outside of header file

I am under the impression that you are allowed to define member functions of a class in one file and then use those functions in another file, as long as both files are compiled and sent to the linker. However, doing this gives me an undefined reference error if I use g++ (4.6.4). Interestingly, using the intel compiler (icpc 11.0) does not give an error and everything works. Is there some flag I can set in g++ to make this work, or is the intel compiler letting me get away with something I shouldn't be doing? Here is some code that reproduces my problem:

class.h:

#ifndef _H
#define _H

typedef class
{
    public:
            int a;
            int b;

            void set(int x, int y);
            int add(void);
} Test;

#endif

class.cpp:

#include "class.h"

void Test::set(int x, int y)
{
    a = x;
    b = y;
}

int Test::add(void)
{
    return a+b;
}

main.cpp:

#include <cstdio>
#include "class.h"

int main(void)
{
    Test n;
    n.set(3, 4);
    printf("%d\n", n.add());

    return 0;
}

To compile, I do:

$ g++ class.cpp main.cpp -o test 
/tmp/ccRxOI40.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `Test::set(int, int)'
main.cpp:(.text+0x26): undefined reference to `Test::add()'
collect2: ld returned 1 exit status

Okay, this is strange, but what happened is that this construct:

typedef class
{
    public:
            int a;
            int b;

            void set(int x, int y);
            int add(void);
} Test;

while legal is not being treated semantically the same by the compiler as:

class Test
{
    public:
            int a;
            int b;

            void set(int x, int y);
            int add(void);
};

The typedef version makes your methods static to the file, as indicated in the nm output:

$ nm class.o
0000000000000024 t _ZN4Test3addEv
0000000000000000 t _ZN4Test3setEii
                 U __gxx_personality_v0

While the class Test version makes them proper methods:

$ nm class2.o
0000000000000024 T _ZN4Test3addEv
0000000000000000 T _ZN4Test3setEii
                 U __gxx_personality_v0

This is why the linker failed to find the symbols.

Edit: As to why this is happening, it seems to be due to an issue with interpreting how the Standard specifies the treatment of the typedef name as a class-name . Newer compilers do not seem to exhibit the same issue. The problem reported in this question was reproduced with g++ 4.4.7.

If you move the code in your class.cpp file into main.cpp and only compile main.cpp , things will work. Alternatively, you can inline the method definitions into class.h .

If you want to leave them as separate translation units, you need to change the class.h file so that your class is defined using the class Test way instead of using the typedef on the anonymous class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM