请帮助解决有关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
提前感谢任何见解。
(对不起,如果这是重新发布 - 我以为我发布了它并且没有看到它......)
答案 0 :(得分:3)
它不起作用。从技术上讲,您遇到的是ODR违规行为,这大致意味着A
和a.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 - 保持不变