【问题标题】:c++ struct declaration collect2: ld returned 1 exit statusc ++ struct声明collect2:ld返回1退出状态
【发布时间】:2015-06-16 13:38:19
【问题描述】:

我设法解决了这个问题,但我不明白为什么会这样,所以我只想对此进行澄清,欢迎任何解释。

我正在练习 Bruce Eckel 的书:用 C++ 思考。 第 1 卷第 4 章中的练习 13 正在创建“表示视频租赁商店中的录像带的抽象数据类型” 根据本章的主题,我假设这应该是一个结构,就像这个非常简单的:

    //video.h
    typedef struct {
        unsigned id;
        char* title;
        float length;
        int inRent;

        void printout();
    } Video;

使用虚拟实现,例如:

//video.cpp
#include "stdio.h"
#include "video.h"

void Video::printout(){     
    printf("id:%u, title:%s, length:%f\n",this->id,this->title,this->length); 
}

还有这样的 main.cpp:

//main.cpp
#include "video.h"
#include "stdio.h"

int main(){

    Video first;

    first.id=1;
    first.title="Some title";
    first.length=1.5;

    first.printout();

    return 0;   
}

当尝试编译和链接gcc -o main.exe main.cpp video.cpp -lstdc++ 时,我在链接时收到以下错误。我也用 g++ 得到了同样的结果

C:\Users\jani\AppData\Local\Temp\cc1KIhpp.o:main.cpp:(.text+0x2e): undefined reference to `Video::printout()'

当我使用结构标识符时 - 比如:typedef struct some_id {...} Video; - 编译并运行没有错误。

这种结构声明在类似情况下如何工作? Eckel 说:“你会注意到结构标识符在开始时被忽略了,因为目标是创建 typedef。但是,有时你可能需要在定义结构时引用它。(.. .)”。 这适用于哪些情况?

非常感谢您的回答。

亚诺斯

【问题讨论】:

  • 我不认为 :: 对 c 有效,所以这不是 C++ 问题吗?
  • 我假设顶部是 video.h,然后是 video.cpp,然后是 main.cpp?
  • 是的,你是对的。 :: 对 C 无效但是 C++ 链接器会产生错误。 “ video.h,然后是 video.cpp,然后是 main.cpp?” - 是的,你是对的。
  • 请就 typedef 结构声明提出建议,不要为包含头文件或编译/链接顺序而烦恼。如果您检查,最初的问题是为什么在“typedef struct”的情况下需要结构标识符才能成功链接。换句话说,为什么可以遵守和链接:typedef struct something {...} Video;,这为什么不起作用:typedef struct {...} Video;

标签: c struct linker g++


【解决方案1】:

为什么不在 video.cpp 文件中提供 stdio 或 iostream 标头。这些标头根据您的系统提供动态链接。如果您仅从简单的 Makefile 进行手动链接,则它可能与操作系统和硬件无关。

更重要的是,您没有在主文件中使用任何 C/C++ 库函数,因此无需在主文件中包含 stdio.h。而是包含它 video.c 文件

【讨论】:

  • "为什么不在 video.cpp 文件中提供 stdio 或 iostream 标头" - 它已经存在! “所以不需要在主目录中包含 stdio.h。而是包含它 video.c 文件” - 我也尝试过,但是导致相同的链接器错误
  • 首先使它们成为 .c 文件而不是 .cpp ..然后在 video.c 文件中写入 #include 而不是“stdio.h”..它给出链接器错误,因为它是可能假设您在当前工作目录中有标题,这是不正确的..
  • 在没有任何链接器选项的情况下编译它。更重要的是,如果它是 C,则不能在结构中创建任何函数。如果你想严格坚持 C++,则删除所有“stdio.h” & 包含 & 代替 video.c 文件中的 printf,使用 std::cout..使用 C 或 C++
  • 谢谢!我决定用纯 C++ 重写它,这可能会解决。
【解决方案2】:

你应该用 g++ 编译(不需要链接 libstdc++,因为所有常用的 linux 发行版都默认使用 libstdc++)并且在 cpp 中声明结构的正确语法是:

struct Video
{
  std::string title; // note that you used char* for title and assigned it a string literal which is of type const char*, there is no implicit conversion for that.
  ...
};

此外,您应该使用 iostream 来进行格式化输出,而不是 printf,它更高效、更不容易出错且更具可读性:

#include <iostream>

void Video::printout(){     
  std::cout << this->id << this->title << this->length << std::endl; 
}

【讨论】:

  • 是的,安娜,你是对的。并行地,我也在测试 C 和 C++ 编译器之间的差异,所以这就是为什么我有意使用 printfuction 来编译两者。
  • 抱歉,您的其他建议不起作用:d:\playground\CPPpractice&gt;g++ -o main.exe video.cpp main.cpp video.cpp main.cpp: In function 'int main()': main.cpp:5:8: error: expected ';' before 'first' Video first; ^ main.cpp:7:2: error: 'first' was not declared in this scope first.id=1; ^
  • 您是否将 video.h 包含在 main.cpp 中? xD
【解决方案3】:

这只是链接顺序的问题。以下应该有效:

g++ -o main.exe video.cpp main.cpp -lstdc++

或(偏执狂):

g++ -o main.exe video.cpp main.cpp video.cpp -lstdc++

【讨论】:

  • 谢谢,但是这两个建议都会导致相同的链接器错误。
  • 哎呀,对,我认为它在技术上是 C++。 (您使用的语言的混淆可能与此有关。)
  • 已经试过了:(d:\playground\CPPpractice&gt;g++ -o main.exe video.cpp main.cpp video.cpp -lstdc++ main.cpp: In function 'int main()': C:\Users\jani\AppData\Local\Temp\cc3coLCU.o:main.cpp:(.text+0x2e): undefined reference to Video::printout()' collect2.exe: error: ld returned 1 exit status)
猜你喜欢
  • 2011-08-26
  • 1970-01-01
  • 2010-12-01
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多