我正在使用C :: B中的一个项目,需要在多个项目文件中使用类的全局实例。 (我对头文件和全局类的使用不熟悉)
我已声明,定义,初始化类和函数:
//在complex.h中
class Julia
{
public:
double R;
double I;
void algorithm();
};
Julia J;
//在complex.cpp中
#include "complex.h"
void Julia::algorithm()
{
//fn body here
}
//在main.cpp
中#include"complex.h"
int main()
{
//calls initialize() and display()
}
void initialize()
{
//...some code(irrelevant)
cin>>J.R>>J.I;
}
void display()
{
J.algorithm();
//some more (irrelevant) code
}
在构建和运行代码时,我得到错误 - "首先在这里定义"并且构建日志显示:
obj \ Debug \ complex.o:complex.cpp :(。bss + 0x3bf0):`J'的多重定义 obj \ Debug \ main.o:C:/Users/ShA/Documents/etf_build/main.cpp:20:首先在这里定义
[这是我的12年级学校项目,我不认为我会被允许使用单身人士(限制),即使他们似乎是合适的。 ]
有人可以指出代码中可能存在的错误以及如何找到我遇到的错误的解决方案吗?
答案 0 :(得分:1)
声明
Julia J;
标头中的是J
的定义,并且通过包含标题,您可以在两个翻译单元中使用此定义:main.cpp
翻译单元和{{ 1}}翻译单位。
链接器不知道它们(原本打算)是相同的定义。
当链接器看到它时,它是同一事物的两个独立且相互冲突的定义。
一个纯粹的技术解决方案是让complex.cpp
成为一个单例,一个简单的方法就是通过函数中的J
变量来实现,这个变量称为“迈耶斯的单身人士”:
static
上面的技术解决方案是不合适的,因为单一例如直接全局变量引入了复杂的任意通信线路,例如,通过您的inline
auto J()
-> Julia&
{
static Julia the_object;
return the_object;
}
功能。
在标题中将变量声明为init
并在相应的实现文件中定义变量,还有一种更有用的技术解决方案。这是额外的好处,因为在更一般的情况下,它存在使用未初始化变量的风险。这被称为“静态初始化顺序惨败”,并在C ++ FAQ中讨论。
您应该更改设计并让extern
创建main
实例,而不是这些技术解决方法。
它可以传递给调用函数。
如果你发现它被传递给了许多函数,特别是作为第一个参数,那么这些函数可能应该是Julia
类的成员函数,或者你应该为此引入一个新类
答案 1 :(得分:1)
in complex.h
Julia J;
这是你的错误。 #includes complex.h的任何源文件都有自己的J
版本。这违反了one definition rule。
如果您使用全局变量J
的唯一位置在int main
中,则没有理由将该变量设为全局变量。在主函数中使J
成为局部变量。声明仅在一个地方使用的全局变量是错误的。
另一方面,如果您在多个文件中使用该变量,那么您所做的也是错误的。在这种情况下,您的complex.h
标头文件应使用J
关键字限定变量extern
。现在,您可以在多个位置引用该全局(但要注意static initialization fiasco)。您可以在多个位置引用该变量。您需要在一个地方定义该变量。
答案 2 :(得分:0)
在static Julia& GetInstance()
声明中(在标题文件中)放置一个class Julia
函数。
将Julia
(Julia J
)的实例放在源文件中。然后在GetInstance()
实现(也在源文件中)内,返回J
。
Complex.h
class Julia
{
public:
double R;
double I;
void algorithm();
static Julia& getInstance();
};
complex.c里
#include "complex.h"
Julia J;
void Julia::algorithm()
{
//fn body here
}
Julia& Julia::getInstance() { return J; }