1

请帮助解决以下有关 C++ 和 g++ 编译和链接的菜鸟问题。本质上,我在 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

提前感谢您的任何见解。

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

4

6 回答 6

3

它不是那样工作的。从技术上讲,您遇到的是 ODR 违规,这大致意味着A两者都a.cpp必须b.cpp是同一件事。它不是。

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

更改a.cpp

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

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

将修复错误。

于 2011-10-03T13:21:23.100 回答
1

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

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

此外,您可能希望将函数标记为显式以避免s在各种不需要的上下文中int被视为's。A

于 2011-10-03T13:22:19.890 回答
0

正确的做法是:

一个.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 - 保持不变

于 2011-10-03T13:32:15.393 回答
0

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

于 2011-10-03T13:23:24.470 回答
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有一个不是构造函数的成员?它怎么知道大小?

于 2011-10-03T13:24:23.900 回答
0

您正在打破单一定义规则,因为您的程序中有两个不同的独立A类。A.cpp 文件的简单通用实现应如下所示:

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

使用“ah”包含类型的正确定义:

#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";
    }
};
于 2011-10-03T13:25:51.780 回答