简体   繁体   English

g ++在visual studio很开心的时候给出了错误 - 未定义的引用

[英]g++ giving errors where visual studio was happy - undefined reference

I have some code that runs fine on Visual Studio, and I am now trying to compile it on g++. 我有一些在Visual Studio上运行良好的代码,我现在正在尝试在g ++上编译它。 It is giving me 'undefined reference to SomeClass::someMethod() const' in a bunch of places. 它在一堆地方给了我'SomeClass :: someMethod()const'的未定义引用。

Most commonly, it's the following situation: 最常见的是,情况如下:

for (const SomeListNode *node = owner->some_list; node != 0; node = node->getNext())

In this case, I get 'undefined reference to SomeListNode::getNext() const'. 在这种情况下,我得到'对SomeListNode :: getNext()const'的未定义引用。 This class's header file is explicitly included. 明确包含此类的头文件。 Why is this not legal in g++? 为什么这在g ++中不合法?

edit for more info 编辑更多信息

I am building with a makefile as such: 我正在使用makefile构建:

CC=g++
CFLAGS=-c -Wall -DDEBUG -g
LDFLAGS=
SOURCES=main.cpp SomeList.cpp SomeListNode.cpp Location.cpp OutputControl.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=theprogram

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o: $(CC) $(CFLAGS) $< -o $@ .cpp.o:$(CC)$(CFLAGS)$ <-o $ @

The line of code originally listed is in the OutputControl.cpp . 最初列出的代码行位于OutputControl.cpp It is taking a pointer to a SomeListNode and iterating over it. 它正在指向SomeListNode并迭代它。 getNext () returns a pointer to another SomeListNode . getNext ()返回指向另一个SomeListNode的指针。

It may also be of note that this is only occurring within static functions. 还可以注意到,这仅发生在静态函数内。

You can only call const-qualified methods on a const-qualified object. 您只能在const限定对象上调用const限定方法。 If getNext() is not const, then you should use SomeListNode *node instead of const SomeListNode *node . 如果getNext()不是const,那么你应该使用SomeListNode *node而不是const SomeListNode *node

Undefined references are linker errors, and these are unrelated to header inclusions. 未定义的引用是链接器错误,它们与头部包含无关。 You have to make sure that you have compiled the definitions of those functions into some object file, and that the object file is passed to the linker. 您必须确保已将这些函数的定义编译到某个目标文件中,并将目标文件传递给链接器。

Beware that if you are compiling to static libraries, the order of the libraries in the linker command line affects the result. 请注意,如果要编译为静态库,则链接器命令行中库的顺序会影响结果。 In particular, if a library depends on other libraries, the dependent should appear in the command line before all the depended on libs. 特别是,如果库依赖于其他库,则所有依赖于库之前 ,依赖项应出现在命令行中。

At any rate, compile each object file separately into a .o or a library and use nm to extract the list of symbols that is defined in each one of the translation units that should tell you whether the definition has been compiled or not and will help you determine the order if you are compiling static libs. 无论如何,将每个目标文件分别编译成.o或库,并使用nm来提取每个翻译单元中定义的符号列表,这些符号应该告诉您定义是否已编译,并将有助于如果要编译静态库,则确定顺序。

I would suggest that you set up dependencies in your makefile so that objects that depends on others are made in the correct order. 我建议您在makefile中设置依赖项,以便依赖于其他对象的对象以正确的顺序生成。 Also setup a clean target that deletes .o files. 还要设置一个删除.o文件的干净目标。 After this run make clean, and make. 在这个运行之后,使干净,并使。

This is the best suggestion I can think of with the information you have given us. 这是我能用你给我们的信息来思考的最佳建议。

Pass all your .cpp files to the g++ compile command. 将所有.cpp文件传递给g ++编译命令。

g++ -g -Wall -o myapp File1.cpp File2.cpp File3.cpp

EDIT: 编辑:

If you're using static libraries, you should add these last on the g++ commandline. 如果您正在使用静态库,则应在g ++命令行上添加最后一个

The linker processes passed files in order, and when it encounters a static library it searches for symbols that are undefined so far . 链接器按顺序处理传递的文件,当它遇到静态库时,它会搜索到目前为止未定义的符号。 You can change this using --whole-archive 您可以使用--whole-archive更改此设置

I recommend to use the nm tool to find out which symbols are involved in you situation. 我建议使用nm工具找出您遇到的符号。 It may look like this: 它可能看起来像这样:

// foo.h
class Foo{
    public:
        void bar();
};

// foo.cpp
#include "foo.h"
void Foo::bar()
{
}

// bar.cpp
#include "foo.h"
void baz()
{
    Foo f;
    f.bar();
}

> nm foo.o
00000000 T _ZN3Foo3barEv

> nm bar.o
00000000 T _Z3bazv
         U _ZN3Foo3barEv
         U __gxx_personality_v0

Here you can see, that bar.o uses an undefined _ZN3Foo3barEv symbol (and a __gxx_personality_v0 , but this is a compiler detail), which is marked U . 在这里你可以看到, _ZN3Foo3barEv使用了一个未定义的_ZN3Foo3barEv符号(和一个__gxx_personality_v0 ,但这是一个编译器细节),标记为U This symbol is defined in foo.o , wehre it is marked T . 这个符号在foo.o定义,我们将它标记为T To get the c++ name form the mangled name, you can use c++filt . 要从受损名称中获取c ++名称,可以使用c++filt

> c++filt _ZN3Foo3barEv
Foo::bar()

> c++filt _Z3bazv
baz()

To debug your problem you inspect both your SomeList.o and OutputControl.o files and look for SomeListNode::getNext instances. 要调试您的问题,请检查SomeList.o和OutputControl.o文件并查找SomeListNode :: getNext实例。 There might be lots of output, so you might want to filter the output with nm file.o | grep 'SomeListNode.*getNext' 可能有很多输出,因此您可能希望使用nm file.o | grep 'SomeListNode.*getNext'过滤输出 nm file.o | grep 'SomeListNode.*getNext' . nm file.o | grep 'SomeListNode.*getNext' Every U marked SomeListNode::getNext symbol form your OutputControl.o file must have an exact match in your SomeList.o file. 每个U标记SomeListNode::getNext符号形式您的OutputControl.o文件必须在SomeList.o文件中具有完全匹配。

Edit : Adjusted answer to the posted Makefile. 编辑 :调整后的Makefile答案。

One difference between Visual Studio and g++ is how they deal with templates. Visual Studio和g ++之间的一个区别是它们如何处理模板。 In Visual Studio, if you define a function in a template, but you never use it anywhere, VS won't typecheck it or generate any code. 在Visual Studio中,如果您在模板中定义一个函数,但从未在任何地方使用它,VS将不会对其进行类型检查或生成任何代码。 In g++ it will typecheck (and it'll give you errors if there are any problems in it). 在g ++中它会进行类型检查(如果有任何问题,它会给你错误)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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