g++非常简单的示例中未定义的引用

发布于 2024-12-08 03:10:25 字数 1423 浏览 0 评论 0原文

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

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

我在以下简单代码中提炼并重现了该问题:

文件: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

感谢提前获得任何见解。

(抱歉,如果这是重新发布的内容 - 我以为我发布了它但没有看到它......)

Please help with the following noob question about C++ and g++ compilation and linking. Essentially I have 2 classes in 2 different files, and can compile them but when I attempt to link, one class can't see the methods of the other, even though I am linking both. Order of object files does not help in this case.

The problem seems related to a non-default constructor that takes a parameter.

I have distilled and reproduced the problem in the following simple code:

File: a.cpp:

#include <iostream>

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

File: a.hpp:

#ifndef __A_H_
#define __A_H_

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

#endif

File 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;
}

Commands I use to build:

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

Alternately, I've tried each of these:

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

Error I get in any of above link scenarios:

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

Thanks in advance for any insight.

(sorry if this is a re-post -- I thought I posted it and don't see it...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

春花秋月 2024-12-15 03:10:25

事实并非如此。从技术上讲,您遇到的是 ODR 违规,这大致意味着 a.cppb.cpp 中的 A 必须是同样的事情。事实并非如此。

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

a.cpp 更改为

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

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

将修复该错误。

It doesn't work that way. What you've come across is technically an ODR violation, which roughly means that A in both a.cpp and b.cpp must be the same thing. It isn't.

Moreover, the constructor is implicitly inline in a.cpp and therefore its code needn't be emitted.

Changing a.cpp to

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

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

will fix the error.

罪#恶を代价 2024-12-15 03:10:25

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

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

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

You a.cpp is violating the one definition rule and redefining A entirely. You just want to define the function in your source file:

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

Also you may want to mark the function explicit to avoid ints being treated as A's in a variety of unwanted contexts.

冷血 2024-12-15 03:10:25

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

In a.cpp, you should #include "a.hpp" and then define the constructor simply as A::A(int i) { ... }. By writing a whole definition of class A with the constructor code within the class body, you're implicitly defining the constructor as an inline function, which is why there's no definition for it in the object file.

萌无敌 2024-12-15 03:10:25

您有两个不同的类(一个包含 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;

怎么可能知道类 A 除了构造函数之外还有其他成员吗?它怎么知道尺寸呢?

You have two different classes (one containing myint, one not) both called class A. You can't do that. Change a.cpp to:

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

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

And change a.hpp to:

#ifndef __A_H_
#define __A_H_

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

#endif

Thank about it, the way you have it, what would the compiler do if someone did this:

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

How could it know that class A has a member other than the constructor? How could it know the size?

故事与诗 2024-12-15 03:10:25

您违反了单一定义规则,因为您的程序中有两个不同的单独 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";
    }
};

You are breaking the One Definition Rule, as you have two distinct separate A classes in your program. The simple common implementation of your A.cpp file should look like:

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

With "a.h" containing the proper definition of the type:

#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;

And then in the implementation of B, you probably meant:

#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";
    }
};
罗罗贝儿 2024-12-15 03:10:25

正确的做法是:

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

The right thing to do is:

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 - remains the same

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文