hew*_*ewy 2 c++ g++ class member-functions undefined-reference
我的印象是,您可以在一个文件中定义类的成员函数,然后在另一个文件中使用这些函数,只要这两个文件都被编译并发送到链接器即可.但是,如果我使用g ++(4.6.4),这样做会给我一个未定义的引用错误.有趣的是,使用intel编译器(icpc 11.0)不会出错,一切正常.是否有一些我可以用g ++设置的标志来使这个工作,或者是英特尔编译器让我逃避我不应该做的事情?以下是一些可以重现我的问题的代码:
class.h:
#ifndef _H
#define _H
typedef class
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
} Test;
#endif
Run Code Online (Sandbox Code Playgroud)
class.cpp:
#include "class.h"
void Test::set(int x, int y)
{
a = x;
b = y;
}
int Test::add(void)
{
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中:
#include <cstdio>
#include "class.h"
int main(void)
{
Test n;
n.set(3, 4);
printf("%d\n", n.add());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为了编译,我做:
$ 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
Run Code Online (Sandbox Code Playgroud)
好的,这很奇怪,但发生的事情是这个结构:
typedef class
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
} Test;
Run Code Online (Sandbox Code Playgroud)
而编译器在法律上没有对legal进行相同的处理:
class Test
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
};
Run Code Online (Sandbox Code Playgroud)
该typedef版本使您的方法static成为文件,如nm输出中所示:
$ nm class.o
0000000000000024 t _ZN4Test3addEv
0000000000000000 t _ZN4Test3setEii
U __gxx_personality_v0
Run Code Online (Sandbox Code Playgroud)
虽然class Test版本使它们成为正确的方法:
$ nm class2.o
0000000000000024 T _ZN4Test3addEv
0000000000000000 T _ZN4Test3setEii
U __gxx_personality_v0
Run Code Online (Sandbox Code Playgroud)
这就是链接器无法找到符号的原因.
编辑:至于为什么会发生这种情况,似乎是由于解释标准如何指定
typedef名称作为类名来处理的问题.较新的编译器似乎没有表现出相同的问题.用g ++ 4.4.7复制了这个问题中报告的问题.
如果将class.cpp文件中的代码移动到main.cpp并且只编译main.cpp,事情就会起作用.或者,您可以将方法定义内联到class.h.
如果要将它们保留为单独的转换单元,则需要更改class.h文件,以便使用class Test方式而不是使用typedef匿名类来定义类.