我正在更新一些旧代码,这些代码有几个POD结构,它们被memset归零(不要责怪我......我没有写这部分)。部分更新将其中一些更改为使用私有内部指针的类,这些指针现在已被memset消除。
所以我在各种结构中添加了[非虚拟] reset()方法,并重构了代码来调用它。
一个特定的结构体开发了一个“未定义的引用`blah :: reset()'”错误。
将其从结构更改为类可修复错误。
在.o文件h上调用nm,该方法的受损函数名称看起来是相同的(无论是类还是结构)。
我在Ubuntu上使用g ++ 4.4.1。
我讨厌这可能是编译器/链接器错误,但我不确定它可能是什么。我错过了结构和类之间的一些根本区别吗?我认为唯一有意义的是公共/私人默认以及每个人对它们的看法。
更新: 它实际上取决于它的声明方式:
typedef struct
{
...
void reset();
} foo;
不会链接。
struct foo
{
...
void reset();
};
很好。
那么,也许只是缺乏对typedef在这种情况下工作方式的理解?
答案 0 :(得分:2)
我认为你的问题(我没有标准引用来支持这个)是因为你的结构没有名字,你的成员函数也没有全球可识别的名称。
虽然您可以使用typedef名称来引入成员函数定义,但如果您希望能够将其链接到不同TU中的定义,则该成员函数必须是命名类型的一部分。
typedef struct S_ { void reset(); } S;
void S::reset() // OK, but the function actually has id: S_::reset()
{
// ...
}
typedef struct { void reset(); } T;
void T::reset() // OK, defintion of anonymous struct's reset(),
// but this isn't an id that can cross TUs.
{
// ...
}
编辑:但这可能是一个gcc错误。
7.1.3 [dcl.typedef]如果typedef声明定义了未命名的类(...),则声明声明的第一个 typedef-name 是该类类型(... )用于表示类型(...)仅用于链接目的(3.5)。
修改强>
或者gcc可能是对的。虽然类通过其typedef名称(3.5 / 4)具有外部链接,但只有当类的名称具有外部链接时,成员函数才具有外部链接。虽然该类具有外部链接,并且它具有用于链接目的的名称,但它仍然是未命名的类,因此它的成员函数没有链接。
答案 1 :(得分:1)
当然,第二个声明是“适当的”C ++做事方式。不过,这个链接对我来说是g ++ 4.4.1:
typedef struct {
void f() {}
} S;
int main() {
S s;
s.f();
}
我必须承认整个结构命名空间对我来说一直是C的黑暗角落之一,但我相信其他人会想出一个解释。
编辑:确定,可以重现问题的极简主义代码:
// str.h
typedef struct {
void f();
} S;
// str.cpp
#include "str.h"
void S :: f() {
}
// sm.cpp
#include "str.h"
int main() {
S s;
s.f();
}
编译:
g++ sm.cpp str.cpp
错误:
undefined reference to S::f()
现在,如果有人能够从标准中给出章节和经文,说明为什么这不起作用 - 显然是一个结构命名空间问题,我会想到。