静态库中使用和引用工程同一个类的时候报错

时间:2022-11-02 20:49:40
做了一个win32 static lib静态库,在这个静态库中使用了一个日志类.然后在另外一个工程中使用了这个创建的静态库,同时在这个测试工程中也使用了静态库中的那个类来记录一些日志,因为测试工程中使用的日志类和静态库中使用的日志类相同,所以编译的时候,报了很多.obj重定义错误,求指教.
1.这个问题是我使用不对吗?
2.如果静态库只是简单的包装了obj,那么下次使用的时候岂不是限制很多,因为引用的工程不能保证不使用静态库中出现的类,或者无意间定义了同名的类.
3.如果是因为静态本身的限制导致这种情况,那么有什么办法,来解决这个问题呢?在引用静态库的工程中使用静态库中出现的类.
以下是引用的测试工程报错的截图和静态库的截图
测试工程:
静态库中使用和引用工程同一个类的时候报错

静态库属性:
静态库中使用和引用工程同一个类的时候报错

26 个解决方案

#1


使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。

#2


引用 1 楼 schlafenhamster 的回复:
使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。


是的 我知道这么使用 那个工程中使用的类我不是从静态库中拿来的,静态库中的这个类我根本没有导出,只是恰好这个类在静态库中和工程中都用到了,难道在静态库中使用了之后,工程中就不能用同一个类吗?静态库中没有导出的类难道编译的时候也会编译到吗?还会再生成对应的OBJ吗?

#3


引用 1 楼 schlafenhamster 的回复:
使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。


您看一下那两个截图 就能看出这个静态库的目录结构和工程的目录结构了

#4


source 目录里 怎么 有 UC_LOG.cpp ???

#5


引用 4 楼 schlafenhamster 的回复:
source 目录里 怎么 有 UC_LOG.cpp ???


对 现在就是静态库中需要记录一些日志,所以我静态库中也用了UC_LOG.cpp

工程里面也需要用到 ,所以工程里面也用了UC_LOG.cpp 但是只是一个很普通的类,静态库中这个类我并没有导出啊.

#6


引用 4 楼 schlafenhamster 的回复:
source 目录里 怎么 有 UC_LOG.cpp ???

在不同的工程中使用了,一个是静态库中的使用,一个是测试工程中使用了,但是静态库里面使用难道和工程里面使用还冲突吗?
静态库中使用和引用工程同一个类的时候报错

#7


“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 

#8


引用 7 楼 schlafenhamster 的回复:
“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 


不是啊 现在没有 UC_LOG.lib 我哪个库导出的是另外的一个 CSerialComm.lib UC_LOG.h 和 UC_LOG.cpp只是在这个库中用到的文件而已.没有UC_LOG.lib存在

导出的是这个
class CSerialComm
{
public:
/**
@brief   打开串口
*/
virtual long openSerial(US_OPENCOM& p_usopencom)=0;
/**
 @brief   关闭串口
*/
virtual BOOL closeSerial(HANDLE& hDevice)=0;
/**
 @brief   串口写数据
*/
virtual long writeSerial(US_WRITECOM& p_writeinfo)=0;
/**
 @brief   串口读数据,在规定的时间内按照指定的字节数读取
*/
virtual long numReadSerial(US_READCOMNUM& p_readinfo)=0;
/**
 @brief   串口读数据,在规定的时间内按照开始和结尾标志进行读取
*/
virtual long markReadSerial(US_READCOMMARK& p_readinfo)=0;
/**
 @brief   发送一条命令
*/
virtual BOOL sendCmd(US_WRITECOM& p_uswrite,US_READCOMNUM& p_usread)=0;
/**
 @brief   发送一条命令,并且判断命令是否成功执行
*/
virtual BOOL bSuccessSendCmd(US_SUCCESSEDCMD& p_ussuccesscmd)=0;
};

SERIALCOMMAPI CSerialComm* _stdcall CreateCommObj();
SERIALCOMMAPI void _stdcall ReleaseCommObj(CSerialComm* pCommObj);

#endif

#9


引用 7 楼 schlafenhamster 的回复:
“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 


或者说我只是导出了
SERIALCOMMAPI CSerialComm* _stdcall    CreateCommObj();
SERIALCOMMAPI void _stdcall            ReleaseCommObj(CSerialComm* pCommObj);


这两个函数而已

#10


静态库 没有 “导出” 的 概念, 动态库 dll 才要 导出

#11


引用 10 楼 schlafenhamster 的回复:
静态库 没有 “导出” 的 概念, 动态库 dll 才要 导出


哦 是不是可以这么理解 使用静态库就相当于使用了所有静态库中的源文件?
然后因为工程中也不能够出现和静态库中相同的文件包括全局变量之类的?

#12


" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace

#13


引用 12 楼 schlafenhamster 的回复:
" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace


我刚刚又做了一个动态库测试了一下 发现在使用动态库的时候就没有关系,我当时就是觉得链接库中的东西不管动态的还是静态的,除了指定的应该对外都是透明的,看来好像不是这么回事

#14


引用 12 楼 schlafenhamster 的回复:
" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace


为什么动态库就没有关系了,动态库的一些知识我也了解,可是还是不怎么明白.

#15


" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.

#16


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.


还真的是链接了 没有问题 测试的使用的win32 dll

#17


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.

静态库中使用和引用工程同一个类的时候报错
这个是截图 动态库中 CInnerClass和工程中的CInnerClass类是一模一样的,但是编译完全没有问题

#18


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.


相同的那个类不是导出的类 导出的类是另外的一个MathDyn那个类

#19


你调试一下,看 会不会到 dll 中去, 

#20


引用 19 楼 schlafenhamster 的回复:
你调试一下,看 会不会到 dll 中去, 


行 按你的方法我试试 话说你起的真早啊 静态库中使用和引用工程同一个类的时候报错

#21


我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib

#22


引用 19 楼 schlafenhamster 的回复:
你调试一下,看 会不会到 dll 中去, 


可以正常调用啊 
静态库中使用和引用工程同一个类的时候报错

静态库中使用和引用工程同一个类的时候报错

#23


引用 21 楼 schlafenhamster 的回复:
我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib


哦 我怀疑您可能理解错我的意思了 
1.我现在动态库中导出的类是 mathdyn 这个类 工程中没有使用过这个类.
2.动态库中有一个写日志的类 CInnerClass,用于记录DLL内部运行的一些信息,同时我觉得这个类方便,所以有把这个CInnerClass类的 CInnerClass.h 和 CInnerClass.cpp 拷贝到工程中使用 记录工程的一些信息.在动态库中的CInnerClass 和工程中的CInnerClass是不会冲突的
3.静态库的时候 同样的CInnerClass是会冲突的.

#24


引用 21 楼 schlafenhamster 的回复:
我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib


您说的那种情况是不是因为你动态库导出的类和项目中控件实现的类是同名的吧?

假设你的动态库这样
class __declspec(dllexport) CYourControl
{
};

然后你项目中的也有这个类 CYourControl

这种应该会出现重定义的问题.

如果你的动态库是这样的

class __declspec(dllexport)CYourControlEx
{
};

class CYourControl
{
};

项目中也有一个
class CYourControl
{
};

这种情况应该不会重定义的

#25


你 的 搞法, 我 觉得 Dll 中 的函数 没有 被 调用, 调用的 是 .cpp 定义中 的 函数。
所以 叫你 调试一下 看看 dll 里 函数 是不是 被 调用了。

#26


引用 25 楼 schlafenhamster 的回复:
你 的 搞法, 我 觉得 Dll 中 的函数 没有 被 调用, 调用的 是 .cpp 定义中 的 函数。
所以 叫你 调试一下 看看 dll 里 函数 是不是 被 调用了。


呵呵 算了 结贴了 你之前跟我说的名字空间的方法挺好用的,问题解决了,至于为什么我再去想吧

谢谢你的解答

#1


使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。

#2


引用 1 楼 schlafenhamster 的回复:
使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。


是的 我知道这么使用 那个工程中使用的类我不是从静态库中拿来的,静态库中的这个类我根本没有导出,只是恰好这个类在静态库中和工程中都用到了,难道在静态库中使用了之后,工程中就不能用同一个类吗?静态库中没有导出的类难道编译的时候也会编译到吗?还会再生成对应的OBJ吗?

#3


引用 1 楼 schlafenhamster 的回复:
使用这个静态库的工程 只要 .h 文件 和 连接 .lib , 不能 有 .cpp 文件。


您看一下那两个截图 就能看出这个静态库的目录结构和工程的目录结构了

#4


source 目录里 怎么 有 UC_LOG.cpp ???

#5


引用 4 楼 schlafenhamster 的回复:
source 目录里 怎么 有 UC_LOG.cpp ???


对 现在就是静态库中需要记录一些日志,所以我静态库中也用了UC_LOG.cpp

工程里面也需要用到 ,所以工程里面也用了UC_LOG.cpp 但是只是一个很普通的类,静态库中这个类我并没有导出啊.

#6


引用 4 楼 schlafenhamster 的回复:
source 目录里 怎么 有 UC_LOG.cpp ???

在不同的工程中使用了,一个是静态库中的使用,一个是测试工程中使用了,但是静态库里面使用难道和工程里面使用还冲突吗?
静态库中使用和引用工程同一个类的时候报错

#7


“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 

#8


引用 7 楼 schlafenhamster 的回复:
“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 


不是啊 现在没有 UC_LOG.lib 我哪个库导出的是另外的一个 CSerialComm.lib UC_LOG.h 和 UC_LOG.cpp只是在这个库中用到的文件而已.没有UC_LOG.lib存在

导出的是这个
class CSerialComm
{
public:
/**
@brief   打开串口
*/
virtual long openSerial(US_OPENCOM& p_usopencom)=0;
/**
 @brief   关闭串口
*/
virtual BOOL closeSerial(HANDLE& hDevice)=0;
/**
 @brief   串口写数据
*/
virtual long writeSerial(US_WRITECOM& p_writeinfo)=0;
/**
 @brief   串口读数据,在规定的时间内按照指定的字节数读取
*/
virtual long numReadSerial(US_READCOMNUM& p_readinfo)=0;
/**
 @brief   串口读数据,在规定的时间内按照开始和结尾标志进行读取
*/
virtual long markReadSerial(US_READCOMMARK& p_readinfo)=0;
/**
 @brief   发送一条命令
*/
virtual BOOL sendCmd(US_WRITECOM& p_uswrite,US_READCOMNUM& p_usread)=0;
/**
 @brief   发送一条命令,并且判断命令是否成功执行
*/
virtual BOOL bSuccessSendCmd(US_SUCCESSEDCMD& p_ussuccesscmd)=0;
};

SERIALCOMMAPI CSerialComm* _stdcall CreateCommObj();
SERIALCOMMAPI void _stdcall ReleaseCommObj(CSerialComm* pCommObj);

#endif

#9


引用 7 楼 schlafenhamster 的回复:
“所以工程里面也用了UC_LOG.cpp ”
为什么 UC_LOG.lib 里 有 工程 要 的函数了。
工程里 不能 加 UC_LOG.cpp 


或者说我只是导出了
SERIALCOMMAPI CSerialComm* _stdcall    CreateCommObj();
SERIALCOMMAPI void _stdcall            ReleaseCommObj(CSerialComm* pCommObj);


这两个函数而已

#10


静态库 没有 “导出” 的 概念, 动态库 dll 才要 导出

#11


引用 10 楼 schlafenhamster 的回复:
静态库 没有 “导出” 的 概念, 动态库 dll 才要 导出


哦 是不是可以这么理解 使用静态库就相当于使用了所有静态库中的源文件?
然后因为工程中也不能够出现和静态库中相同的文件包括全局变量之类的?

#12


" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace

#13


引用 12 楼 schlafenhamster 的回复:
" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace


我刚刚又做了一个动态库测试了一下 发现在使用动态库的时候就没有关系,我当时就是觉得链接库中的东西不管动态的还是静态的,除了指定的应该对外都是透明的,看来好像不是这么回事

#14


引用 12 楼 schlafenhamster 的回复:
" 使用静态库就相当于使用了所有静态库中的源文件"
可以这么理解。
静态库 就是一个函数 集合。 
同名 函数 就是名字冲突。

你的 那个 cpp 还要 与 静态库一起用的 话 
要 加 namespace


为什么动态库就没有关系了,动态库的一些知识我也了解,可是还是不怎么明白.

#15


" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.

#16


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.


还真的是链接了 没有问题 测试的使用的win32 dll

#17


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.

静态库中使用和引用工程同一个类的时候报错
这个是截图 动态库中 CInnerClass和工程中的CInnerClass类是一模一样的,但是编译完全没有问题

#18


引用 15 楼 schlafenhamster 的回复:
" 发现在使用动态库的时候就没有关系,"
你是没有 连接 dll 吧;
 用的还是  .cpp 里 的 函数.


相同的那个类不是导出的类 导出的类是另外的一个MathDyn那个类

#19


你调试一下,看 会不会到 dll 中去, 

#20


引用 19 楼 schlafenhamster 的回复:
你调试一下,看 会不会到 dll 中去, 


行 按你的方法我试试 话说你起的真早啊 静态库中使用和引用工程同一个类的时候报错

#21


我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib

#22


引用 19 楼 schlafenhamster 的回复:
你调试一下,看 会不会到 dll 中去, 


可以正常调用啊 
静态库中使用和引用工程同一个类的时候报错

静态库中使用和引用工程同一个类的时候报错

#23


引用 21 楼 schlafenhamster 的回复:
我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib


哦 我怀疑您可能理解错我的意思了 
1.我现在动态库中导出的类是 mathdyn 这个类 工程中没有使用过这个类.
2.动态库中有一个写日志的类 CInnerClass,用于记录DLL内部运行的一些信息,同时我觉得这个类方便,所以有把这个CInnerClass类的 CInnerClass.h 和 CInnerClass.cpp 拷贝到工程中使用 记录工程的一些信息.在动态库中的CInnerClass 和工程中的CInnerClass是不会冲突的
3.静态库的时候 同样的CInnerClass是会冲突的.

#24


引用 21 楼 schlafenhamster 的回复:
我搞过一个 用户控件, 用户有2种选择
1. 用 DLL ,这时项目中 删除 控件。Cpp 文件
2. 用 源代码 ,这时 项目中 删除 链接 控件。lib


您说的那种情况是不是因为你动态库导出的类和项目中控件实现的类是同名的吧?

假设你的动态库这样
class __declspec(dllexport) CYourControl
{
};

然后你项目中的也有这个类 CYourControl

这种应该会出现重定义的问题.

如果你的动态库是这样的

class __declspec(dllexport)CYourControlEx
{
};

class CYourControl
{
};

项目中也有一个
class CYourControl
{
};

这种情况应该不会重定义的

#25


你 的 搞法, 我 觉得 Dll 中 的函数 没有 被 调用, 调用的 是 .cpp 定义中 的 函数。
所以 叫你 调试一下 看看 dll 里 函数 是不是 被 调用了。

#26


引用 25 楼 schlafenhamster 的回复:
你 的 搞法, 我 觉得 Dll 中 的函数 没有 被 调用, 调用的 是 .cpp 定义中 的 函数。
所以 叫你 调试一下 看看 dll 里 函数 是不是 被 调用了。


呵呵 算了 结贴了 你之前跟我说的名字空间的方法挺好用的,问题解决了,至于为什么我再去想吧

谢谢你的解答