Eclipse (C++) 的未定义引用错误
Undefined reference error with Eclipse (C++)
我一直在学习 C++,并且一直在使用一些测试代码来调试一个更大项目的各个部分。我正在尝试使用另一个文件中的对象,但尽管包含了适当的头文件,但我仍然收到未定义的引用错误。我在 Linux 上使用带有 C++ CDT 的 Eclipse。代码如下所示:
A.cpp
class A {
private:
int i;
int j;
public:
A(int i1, int i2) {
i = i1;
j = i2;
}
int sum() {
return (i+j);
}
};
a.h
#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;
}
这是我的语法问题,还是我需要深入研究编译器?
问题是 main.cpp
只看到 header a.h
中 class 的定义,不包含构造函数和成员函数的定义.
在A.cpp
中定义了这些函数,但默认情况下它们被定义为内联函数。所以再次 main.cpp 没有看到他们的定义。
考虑到根据C++标准(3.2一定义规则)
6 There can be more than one definition of a class type (Clause 9),
enumeration type (7.2), inline function with external linkage (7.1.2),
class template (Clause 14), non-static function template (14.5.6),
static data member of a class template (14.5.1.3), member function of
a class template (14.5.1.1), or template specialization for which some
template parameters are not specified (14.7, 14.5.5) in a program
provided that each definition appears in a different translation unit,
and provided the definitions satisfy the following requirements. Given
such an entity named D defined in more than one translation unit, then
(6.1) — each definition of D shall consist of the same sequence of
tokens; and
所以在 A.cpp 你应该写
#include "a.h"
A::A(int i1, int i2) {
i = i1;
j = i2;
}
int A::sum() {
return (i+j);
}
另外,class 定义应以分号结尾。
这不是您在 C++ 中拆分 public 接口和 class 私有实现的方式。
为了编译 main 中的这段代码
A a(1,2);
编译器需要已经知道 A
的大小 - 这是因为存储是在本地分配的,即使调用初始化它的构造函数是在别处定义的。
您可以通过使用指针(最好是智能指针)或 pimpl 习惯用法来避免这种耦合,但这是默认设置。
这意味着你的class在头部的定义必须是
class A {
int i;
int j;
public:
A(int i1, int i2);
int sum();
};
(请注意 class 定义末尾的 '
,这很重要 - 您还需要确保使用 #endif
终止包含守卫)。
实现的 cpp 文件应该如下所示
#include "a.h"
A::A(int i1, int i2) : i(i1), j(i2)
{
}
int A::sum()
{
return (i+j);
}
你只能定义 A
一次,所以你不能在头文件和实现文件中有不同的定义。
现在这些问题已解决:如果您的原始错误仍然存在,则残留问题可能与您的 compile/link 设置有关。
每个人关于定义的说法都是正确的。但是还有其他一些问题:
- class 定义
的右大括号后需要一个分号 ;
- 您需要在
#ifndef
之后添加一个 #endif
指令(通常位于头文件的末尾)
- 即使使用
#include <iostream>
,cout
也不会导出到 top-level 命名空间。您必须将其称为 std::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;
}
我一直在学习 C++,并且一直在使用一些测试代码来调试一个更大项目的各个部分。我正在尝试使用另一个文件中的对象,但尽管包含了适当的头文件,但我仍然收到未定义的引用错误。我在 Linux 上使用带有 C++ CDT 的 Eclipse。代码如下所示:
A.cpp
class A {
private:
int i;
int j;
public:
A(int i1, int i2) {
i = i1;
j = i2;
}
int sum() {
return (i+j);
}
};
a.h
#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;
}
这是我的语法问题,还是我需要深入研究编译器?
问题是 main.cpp
只看到 header a.h
中 class 的定义,不包含构造函数和成员函数的定义.
在A.cpp
中定义了这些函数,但默认情况下它们被定义为内联函数。所以再次 main.cpp 没有看到他们的定义。
考虑到根据C++标准(3.2一定义规则)
6 There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
(6.1) — each definition of D shall consist of the same sequence of tokens; and
所以在 A.cpp 你应该写
#include "a.h"
A::A(int i1, int i2) {
i = i1;
j = i2;
}
int A::sum() {
return (i+j);
}
另外,class 定义应以分号结尾。
这不是您在 C++ 中拆分 public 接口和 class 私有实现的方式。
为了编译 main 中的这段代码
A a(1,2);
编译器需要已经知道 A
的大小 - 这是因为存储是在本地分配的,即使调用初始化它的构造函数是在别处定义的。
您可以通过使用指针(最好是智能指针)或 pimpl 习惯用法来避免这种耦合,但这是默认设置。
这意味着你的class在头部的定义必须是
class A {
int i;
int j;
public:
A(int i1, int i2);
int sum();
};
(请注意 class 定义末尾的 '
,这很重要 - 您还需要确保使用 #endif
终止包含守卫)。
实现的 cpp 文件应该如下所示
#include "a.h"
A::A(int i1, int i2) : i(i1), j(i2)
{
}
int A::sum()
{
return (i+j);
}
你只能定义 A
一次,所以你不能在头文件和实现文件中有不同的定义。
现在这些问题已解决:如果您的原始错误仍然存在,则残留问题可能与您的 compile/link 设置有关。
每个人关于定义的说法都是正确的。但是还有其他一些问题:
- class 定义 的右大括号后需要一个分号
- 您需要在
#ifndef
之后添加一个#endif
指令(通常位于头文件的末尾) - 即使使用
#include <iostream>
,cout
也不会导出到 top-level 命名空间。您必须将其称为std::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;
}