Class 在 C++ 库和程序中具有相同的接口。 exe版本是
Class with same interface in c++ lib and program. Exe version is
我有一个静态库,它有一个 class 栏,在 c++ 库和程序的头文件中定义了相同的接口。该 exe 具有略微不同的 Bar.cpp 源代码,并创建具有不同值的对象。请参阅下面的代码。
静态库文件。 (Lib_project\Foo_lib)
Lib_project\foo_lib.h
class Foo
{
public:
int printBarA() const;
};
Lib_project\foo_lib.cpp
#include <iostream>
#include "Foo_lib.h"
#include "Bar.h"
int Foo::printBarA() const
{
Bar bar;
std::cout << "bar.getA() : " << bar.getA() << std::endl;
return 0;
}
Lib_project\Bar.h
// Lib Bar definition
class Bar
{
public:
Bar();
int getA() const;
private:
int a;
};
Lib_project\Bar.cpp
#include "Bar.h"
Bar::Bar() : a(99) {} // Different value here
int Bar::getA() const { return a; }
主程序exe代码(shared_class)
Bar.h
// exe Bar definition
class Bar
{
public:
Bar();
int getA() const;
private:
int a;
};
bar.cpp
#include "Bar.h"
Bar::Bar() : a(66) { } // Different value here
int Bar::getA() const { return a; }
main.cpp
#include "Lib_project\Foo_lib.h"
int main(int argc, char** argv)
{
Foo foo;
foo.printBarA();
return 0;
}
编译后的程序输出如下。 Foo_lib 方法 Foo::printBarA() 根据 main.exe Bar.cpp 中定义的 a=66 创建 Bar 对象;而不是在具有 a=99 的库 Bar.cpp 中定义;
D:\shared_class>Release\shared_class.exe
bar.getA() : 66
编译为 DLL 在 windows 上修复了它,但在 linux 上作为共享库问题仍然存在,所以我需要一个独立于平台的修复。
所以我的问题是:
- 为什么会这样? (我正在考虑如何处理被丢弃的 .obj 文件
在 link 时间。)
- 我有什么选择可以停止此行为,以便使用 Foo_lib.lib 中的 Bar.cpp 并打印 bar.getA() : 99?
- 将所有库文件包装在命名空间中?或者重命名 classes?我有
实际案例中有很多文件。有没有 linker 或编译器
比可行的选项?
谢谢
分辨率:
我必须将每个 class 包装在命名空间中以避免任何冲突。现在一切都按预期工作。
您在同一程序中使用相同的 class (::Bar
) 和两个略有不同的定义,这违反了单一定义规则 (ODR)。您的程序的行为完全未定义。
要解决此问题,您必须重命名 Bar
的一个定义,方法是更改实际名称或将其放入命名空间。
(至于为什么会发生这种情况的技术细节,这是由于链接器使用静态库来解决依赖关系的方式。但由于它是 UB,因此您不能依赖它。)
我有一个静态库,它有一个 class 栏,在 c++ 库和程序的头文件中定义了相同的接口。该 exe 具有略微不同的 Bar.cpp 源代码,并创建具有不同值的对象。请参阅下面的代码。
静态库文件。 (Lib_project\Foo_lib)
Lib_project\foo_lib.h
class Foo
{
public:
int printBarA() const;
};
Lib_project\foo_lib.cpp
#include <iostream>
#include "Foo_lib.h"
#include "Bar.h"
int Foo::printBarA() const
{
Bar bar;
std::cout << "bar.getA() : " << bar.getA() << std::endl;
return 0;
}
Lib_project\Bar.h
// Lib Bar definition
class Bar
{
public:
Bar();
int getA() const;
private:
int a;
};
Lib_project\Bar.cpp
#include "Bar.h"
Bar::Bar() : a(99) {} // Different value here
int Bar::getA() const { return a; }
主程序exe代码(shared_class)
Bar.h
// exe Bar definition
class Bar
{
public:
Bar();
int getA() const;
private:
int a;
};
bar.cpp
#include "Bar.h"
Bar::Bar() : a(66) { } // Different value here
int Bar::getA() const { return a; }
main.cpp
#include "Lib_project\Foo_lib.h"
int main(int argc, char** argv)
{
Foo foo;
foo.printBarA();
return 0;
}
编译后的程序输出如下。 Foo_lib 方法 Foo::printBarA() 根据 main.exe Bar.cpp 中定义的 a=66 创建 Bar 对象;而不是在具有 a=99 的库 Bar.cpp 中定义;
D:\shared_class>Release\shared_class.exe
bar.getA() : 66
编译为 DLL 在 windows 上修复了它,但在 linux 上作为共享库问题仍然存在,所以我需要一个独立于平台的修复。
所以我的问题是:
- 为什么会这样? (我正在考虑如何处理被丢弃的 .obj 文件 在 link 时间。)
- 我有什么选择可以停止此行为,以便使用 Foo_lib.lib 中的 Bar.cpp 并打印 bar.getA() : 99?
- 将所有库文件包装在命名空间中?或者重命名 classes?我有 实际案例中有很多文件。有没有 linker 或编译器 比可行的选项?
谢谢
分辨率:
我必须将每个 class 包装在命名空间中以避免任何冲突。现在一切都按预期工作。
您在同一程序中使用相同的 class (::Bar
) 和两个略有不同的定义,这违反了单一定义规则 (ODR)。您的程序的行为完全未定义。
要解决此问题,您必须重命名 Bar
的一个定义,方法是更改实际名称或将其放入命名空间。
(至于为什么会发生这种情况的技术细节,这是由于链接器使用静态库来解决依赖关系的方式。但由于它是 UB,因此您不能依赖它。)