Eclipse 的未定义引用错误 (C++)

Undefined reference error with Eclipse (C++)

提问人:Attila the Pun 提问时间:4/11/2018 最后编辑:Attila the Pun 更新时间:4/12/2018 访问量:512

问:

我一直在学习 C++,并且一直在使用一些测试代码来调试一个更大项目的各个部分。我正在尝试使用另一个文件中的对象,但尽管包含了适当的头文件,但我仍然收到未定义的引用错误。我在 Linux 上使用带有 C++ CDT 的 Eclipse。代码如下所示:

.cpp

class A {

   private:

      int i;
      int j;

   public:

      A(int i1, int i2) {
         i = i1;
         j = i2;
      }

      int sum() {
         return (i+j);          
      }
};

#ifndef A_H_
#define A_H_

class A {
   public:
      A(int i1, int i2);
      int sum();
};
#endif

main.cpp

#include <iostream>
#include "a.h"

int main() {
   A a(1,2); //undefined reference to 'A::A(int,int)'
   std::cout << a.sum(); //undefined reference to 'A::sum(void)'
   return 0;
}

这是我的语法有问题,还是我需要在编译器中四处挖掘?

c++ eclipse-cdt 头文件 undefined-reference

评论

0赞 Fred Larson 4/11/2018
嗯,你的文件底部有一个吗?#endifa.h
0赞 Attila the Pun 4/12/2018
那是个错别字。米娅·库尔帕

答:

0赞 Vlad from Moscow 4/11/2018 #1

问题在于,在标头中只能看到类的定义,而不包含构造函数和成员函数的定义。main.cppa.h

在这些函数中定义,但默认情况下它们被定义为内联函数。所以 main.cpp 再次看不到它们的定义。A.cpp

考虑到根据 C++ 标准(3.2 一个定义规则)

6 类类型可以有多个定义(第 9 条), 枚举类型 (7.2)、带外部链接的内联函数 (7.1.2)、 类模板(第 14 条)、非静态函数模板(14.5.6)、 类模板 (14.5.1.3) 的静态数据成员,其成员函数 类模板 (14.5.1.1) 或模板专用化,其中某些 未在程序中指定模板参数(14.7、14.5.5) 前提是每个定义出现在不同的翻译单元中, 前提是定义满足以下要求。鉴于 在多个翻译单元中定义的名为 D 的实体,则

(6.1) — D 的每个定义应由相同的序列组成 代币;和

所以在 A.cpp 中你应该写

#include "a.h"


  A::A(int i1, int i2) {
     i = i1;
     j = i2;
  }

  int A::sum() {
     return (i+j);          
  }

此外,类定义应以分号结尾。

0赞 Useless 4/11/2018 #2

这不是在 C++ 中拆分类的公共接口和私有实现的方式。

为了让这段代码在 main 中编译

   A a(1,2);

编译器需要已经知道 - 这是因为存储是在本地分配的,即使调用初始化它的构造函数是在其他地方定义的。A

您可以通过使用指针(最好是智能指针)或疙瘩成语来避免这种耦合,但这是默认设置。

这意味着标头中类的定义必须是

class A {
    int i;
    int j;

public:
    A(int i1, int i2);
    int sum();
};

(请注意类定义末尾的 ),这很重要 - 您还需要确保使用 )。'#endif

然后,实现 cpp 文件应如下所示

#include "a.h"

A::A(int i1, int i2) : i(i1), j(i2)
{
}

int A::sum()
{
  return (i+j);          
}

您只能定义一次,因此标头和实现文件中不能有不同的定义A

现在这些问题已经修复:如果原始错误仍然存在,则残留问题可能出在编译/链接设置上。

0赞 tel 4/11/2018 #3

每个人都在说定义的东西是真的。但还有其他几个问题:

  • 在类定义的右大括号后需要一个分号;
  • 您需要在 之后有一个指令(通常位于头文件的末尾)#endif#ifndef
  • 即使使用 ,也不会导出到顶级命名空间。你必须把它称为#include <iostream>coutstd::cout

下面是一个完整的工作示例。这是一个文件,但如果你想,你可以自己拆分它:

#ifndef A_H_
#define A_H_

class A {
   private:

      int i;
      int j;

   public:
      A(int i1, int i2);
      int sum();
};
#endif

A::A(int i1, int i2) {
    i = i1;
    j = i2;
}

int A::sum() {
    return (i+j);          
}

#include <iostream>

int main() {
   A a(1,2);
   std::cout << a.sum();
   return 0;
}

自己在线尝试一下