我的印象是,您可以在一个文件中定义类的成员函数,然后在另一个文件中使用这些函数,只要这两个文件都被编译并发送到链接器即可。但是,如果我使用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
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;
}
要编译,我这样做:
$ 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
答案 0 :(得分:5)
好的,这很奇怪,但发生的事情是这个结构:
typedef class
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
} Test;
虽然编译器在法律上没有对legal进行相同的处理:
class Test
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
};
typedef
版本将您的方法static
设置为文件,如nm
输出中所示:
$ nm class.o
0000000000000024 t _ZN4Test3addEv
0000000000000000 t _ZN4Test3setEii
U __gxx_personality_v0
虽然class Test
版本使它们成为正确的方法:
$ nm class2.o
0000000000000024 T _ZN4Test3addEv
0000000000000000 T _ZN4Test3setEii
U __gxx_personality_v0
这就是链接器无法找到符号的原因。
修改:至于为什么会发生这种情况,似乎是由于解释标准如何指定
typedef
名称作为类的处理方式的问题 - 名称的。较新的编译器似乎没有表现出相同的问题。这个问题中报告的问题是用g ++ 4.4.7复制的。
如果您将class.cpp
文件中的代码移至main.cpp
并仅编译main.cpp
,那么事情就会奏效。或者,您可以将方法定义内联到class.h
。
如果您想将它们保留为单独的翻译单元,则需要更改class.h
文件,以便使用class Test
方式定义您的课程,而不是使用typedef
匿名课。