在.h文件中使用非常简单的C ++函数链接错误

时间:2011-06-21 12:03:03

标签: c++ visual-studio linker compiler-errors

我已经制作了两个“演员阵容”的功能。一个32/64位指针变成一个double。单独使用时代码工作(只有.h和包含它的.cpp)但是当在其他地方使用.h时(复制到项目目录中然后包含它)ith throws'已经定义了'链接时.h文件中所有函数的错误。

.h文件的源代码如下:

#pragma once
#ifndef __FLOATCAST_H
#define __FLOATCAST_H

//A quick and dirty way of casting pointers into doubles and back
//Should work with BOTH 64bit and 32bit pointers
union ptr_u {
    double d;
    void* p;
};

double ptr2double(void* pv){
    ptr_u ptr;
    ptr.p = pv;
    return (ptr.d);
};

void* double2ptr(double dv){
    ptr_u ptr;
    ptr.d = dv;
    return(ptr.p);
};

#endif

该链接表示已经在文件源文件(而不是他的.obj)上定义了这些函数,但不包含此文件。

编辑: 为什么我想要一个指针内部双?因为我需要Lua(5.1)来回调一个对象成员函数。

EDIT2: Lua提供了一种存储用户数据的方法,它似乎是足够的解决方案,而不是投射指针(见注释)

4 个答案:

答案 0 :(得分:8)

将内容标记为内联

inline double ptr2double(void* pv){
    ptr_u ptr;
    ptr.p = pv;
    return (ptr.d);
};

inline void* double2ptr(double dv){
    ptr_u ptr;
    ptr.d = dv;
    return(ptr.p);
};

您可以看到,当您在两个单独的源文件(翻译单元)中包含相同的功能时,您将获得多个定义。您通常有两种选择:

  • 在.h文件中修改您的功能,在单独的.cpp文件中修改定义
  • 使您的函数内联并将它们保存在.h文件中

C ++的单一定义规则禁止对非内联函数进行多重定义。

修改 #ifdef警卫防止多次加入 源文件。但您确实可以将.h文件包含在不同的.cpp文件中。 ODR适用于整个程序中的定义,而不仅仅是单个文件。

EDIT2 的 经过一番评论后,我觉得我必须在这里加入这些信息,以免产生任何误解。在C ++中,有关内联函数和非内联函数的不同规则,例如ODR的特殊情况。现在,您可以将任何函数(无论是长函数还是递归函数)标记为内联函数,并且特殊规则将适用于它们。编译器是否决定实际内联它(即代替代码而不是调用)是完全不同的事情,即使你没有将函数标记为内联,它也可以做,并且可以决定不做即使你将其标记为内联。

答案 1 :(得分:3)

规范的方式是:

floatcast.h

#pragma once
#ifndef __FLOATCAST_H
#define __FLOATCAST_H

//A quick and dirty way of casting pointers into doubles and back
//Should work with BOTH 64bit and 32bit pointers
union ptr_u {
    double d;
    void* p;
};

double ptr2double(void* pv);
void* double2ptr(double dv);

#endif

floatcast.cpp

#include "floatcast.h"

double ptr2double(void* pv){
    ptr_u ptr;
    ptr.p = pv;
    return (ptr.d);
};

void* double2ptr(double dv){
    ptr_u ptr;
    ptr.d = dv;
    return(ptr.p);
};    

答案 2 :(得分:0)

将您的代码放在.cpp文件中,然后在.h文件中放入原型 -

double ptr2double(void* pv);
void* double2ptr(double dv);

或保持代码不变,并为每个函数定义添加“内联”,以便在每个模块中定义它们

虽然我不认为你的代码实际上会做任何非常有用的事情。 访问联合的不同成员而不是用于存储数据的成员,这是未定义的行为。再加上即使“工作”,我也想不到你打算如何使用它,你将存储一个双重读取32位的指针(在32位机器上)...你怎么可能使用它这对于什么?

答案 3 :(得分:0)

您收到错误,因为函数被编译两次(每次包含头文件),因此将所有目标文件组合到最终可执行文件中的链接器会看到函数的多个定义。

就像Armen写的那样,一种解决方案就是使函数内联。这样,只要使用它们,就会复制函数的代码。这是一个可行的解决方案,因为函数非常小,代码不会变得非常臃肿。如果您在头文件中有任何更大的函数,或者您需要更好地组织代码,则应该从头文件中获取代码并将其放入cpp文件中(如sehe的答案)。