g ++ undefined reference在一个非常简单的例子中

时间:2011-10-03 13:18:19

标签: c++ linker g++ undefined-reference

请帮助解决有关C ++和g ++编译和链接的以下noob问题。基本上我在2个不同的文件中有2个类,并且可以编译它们但是当我尝试链接时,一个类无法看到另一个类的方法,即使我正在链接它们。在这种情况下,目标文件的顺序没有帮助。

问题似乎与带参数的非默认构造函数有关。

我已经通过以下简单代码提炼并重现了该问题:

档案:a.cpp

#include <iostream>

class A
{
  public:
  int my_int;
    A(int i) {
      my_int = i;
      std::cout << "A";
    }
};

文件:a.hpp:

#ifndef __A_H_
#define __A_H_

class A
{
  public:
  A(int i);
};

#endif

文件b.cpp:

#include <iostream>

using namespace std;

#include <a.hpp>

class B
{
  public:
  int my_int;
    B(int i) {
      my_int = i;
      A a(i);
      cout << "B\n";
    }
};

int main(int argc, char* argv[])
{
  B b(5);
  cout << "hello world: ";
  cout.flush();
  return 0;
}

我用来构建的命令:

g++ -c -I. a.cpp
g++ -c -I. b.cpp
g++ -o c_test a.o b.o

或者,我尝试了以下各项:

g++ -o c_test b.o a.o
g++ -I. -o c_test a.cpp b.cpp
g++ -I. -o c_test b.cpp a.cpp

我在以上任何链接方案中遇到错误:

b.o: In function `B::B(int)':
b.cpp:(.text._ZN1BC1Ei[B::B(int)]+0x1c): undefined reference to `A::A(int)'
collect2: ld returned 1 exit status

提前感谢任何见解。

(对不起,如果这是重新发布 - 我以为我发布了它并且没有看到它......)

6 个答案:

答案 0 :(得分:3)

它不起作用。从技术上讲,您遇到的是ODR违规行为,这大致意味着Aa.cpp中的b.cpp必须是同一件事。事实并非如此。

此外,构造函数在a.cpp中隐式inline,因此无需发出其代码。

a.cpp更改为

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

A::A(int i) {
      my_int = i;
      std::cout << "A";
}

将修复错误。

答案 1 :(得分:1)

a.cpp违反了一个定义规则并完全重新定义A。您只想在源文件中定义该函数:

A::A(int i) {
  my_int = i;
  std::cout << "A";
}

此外,您可能需要明确标记该功能,以避免int在各种不需要的情境中被视为A

答案 2 :(得分:0)

a.cpp中,您应#include "a.hpp",然后将构造函数定义为A::A(int i) { ... }。通过在class A主体中使用构造函数代码编写class的完整定义,您隐式将构造函数定义为内联函数,这就是为什么没有定义它在目标文件中。

答案 3 :(得分:0)

您有两个不同的类(一个包含myint,一个不包含),都称为class A。你不能这样做。将a.cpp更改为:

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

A::A(int i) {
  my_int = i;
  std::cout << "A";
}

并将a.hpp更改为:

#ifndef __A_H_
#define __A_H_

class A
{
 public:
 int my_int;
 A(int i);
};

#endif

感谢它,你拥有它的方式,如果有人这样做,编译器会做什么:

#include "a.hpp"
// ...
    A foo(3);
    cout << sizeof(foo) << endl;

怎么知道class A有一个构造函数以外的成员?怎么知道它的大小?

答案 4 :(得分:0)

您违反了One Definition Rule,因为您的程序中有两个不同的A类。 A.cpp文件的简单常见实现应如下所示:

#include "a.h" // where the definition of the type is
A::A( int x ) : myint(i) {}

“a.h”包含类型的正确定义:

#ifndef A_H_ // identifiers containing double underscores (__) are reserved, don't use them
#define A_H_
class A
{
  int myint; // This must be present in the definition of the class!
public:
  A(int i);
};
#endif;

然后在B的实现中,你可能意味着:

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

using namespace std;  // I don't like `using`, but if you use it, do it after all includes!
class B {
public:
//   int my_int;      // do you really want to hide A::my_int??
    B(int i) : A(i) { // use the initializer list
      cout << "B\n";
    }
};

答案 5 :(得分:0)

正确的做法是:

<强> a.hpp

#ifndef __A_H_
#define __A_H_

class A
{
  public:
    int my_int;
  A(int i);
};

#endif

<强> a.cpp

#include <iostream>

#include "a.hpp"

A::A(int i) {
      my_int = i;
      std::cout << "A";
    }

b.cpp - 保持不变