class 的全局实例(跨多个文件)
Global instances of class (across multiple files)
我正在 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
}
在构建和 运行 代码时,我收到错误 - "first defined here" 并且构建日志显示:
obj\Debug\complex.o:complex.cpp:(.bss+0x3bf0): ‘J’的多重定义
obj\Debug\main.o:C:/Users/ShA/Documents/etf_build/main.cpp:20: 首先在这里定义
[这是我 12 年级的学校项目,我不认为我会被允许使用单例(限制),即使它们看起来很合适。 ]
有人可以指出代码中可能存在的错误以及如何找到解决我遇到的错误的方法吗?
声明
Julia J;
在您的 header 中是 J
的 定义 ,并且通过包含 header 您在两个翻译单元中拥有此定义: main.cpp
翻译单元和 complex.cpp
翻译单元。
链接器不知道它们是(本来是)相同的定义。
在链接器看来,它是同一事物的两个独立且相互冲突的定义。
一个纯粹的技术解决方案是使J
成为一个单例,一个简单的方法是通过函数中的static
变量, 被称为“Meyers 单例”:
inline
auto J()
-> Julia&
{
static Julia the_object;
return the_object;
}
上面的技术方案不好,因为单例和直接全局变量一样,引入了复杂的任意通信线路,例如通过您的 init
函数。
还有一个更不好的技术方案,就是在header中声明变量为extern
,然后在对应的实现文件中定义。这是非常不好的,因为在更一般的情况下,它冒着使用未初始化变量的风险。这称为“静态初始化顺序失败”,在 C++ FAQ 中进行了讨论。
您应该更改设计并让 main
创建 Julia
实例,而不是这些技术解决方法。
它可以传递给调用的函数。
如果你发现它被传递给了一些函数,特别是作为第一个参数,那么也许这些函数应该是 Julia
class 的成员函数,或者你应该然后为此引入一个新的class。
in complex.h
Julia J;
这是你的错误。 #includes complex.h 的任何源文件都有自己的 J
版本。这违反了 one definition rule.
如果您使用全局变量 J
的唯一地方是在您的 int main
中,则没有理由将该变量设置为全局变量。使 J
成为主函数中的局部变量。声明一个只在一个地方使用的全局变量是错误的。
另一方面,如果您在多个文件中使用该变量,那么您的做法也是错误的。在这种情况下,您的 complex.h
头文件应使用 extern
关键字限定您的变量 J
。现在您可以在多个地方引用该全局变量(但要注意 static initialization fiasco)。您可以在多个地方引用该变量。您需要在一个地方定义该变量。
在您的 class Julia
声明中放置一个 static Julia& GetInstance()
函数(在头文件中)。
在源文件中放置一个 Julia
(Julia J
) 的实例。然后在 GetInstance()
实现中(也在源文件中), return 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; }
我正在 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
}
在构建和 运行 代码时,我收到错误 - "first defined here" 并且构建日志显示:
obj\Debug\complex.o:complex.cpp:(.bss+0x3bf0): ‘J’的多重定义 obj\Debug\main.o:C:/Users/ShA/Documents/etf_build/main.cpp:20: 首先在这里定义
[这是我 12 年级的学校项目,我不认为我会被允许使用单例(限制),即使它们看起来很合适。 ]
有人可以指出代码中可能存在的错误以及如何找到解决我遇到的错误的方法吗?
声明
Julia J;
在您的 header 中是 J
的 定义 ,并且通过包含 header 您在两个翻译单元中拥有此定义: main.cpp
翻译单元和 complex.cpp
翻译单元。
链接器不知道它们是(本来是)相同的定义。
在链接器看来,它是同一事物的两个独立且相互冲突的定义。
一个纯粹的技术解决方案是使J
成为一个单例,一个简单的方法是通过函数中的static
变量, 被称为“Meyers 单例”:
inline
auto J()
-> Julia&
{
static Julia the_object;
return the_object;
}
上面的技术方案不好,因为单例和直接全局变量一样,引入了复杂的任意通信线路,例如通过您的 init
函数。
还有一个更不好的技术方案,就是在header中声明变量为extern
,然后在对应的实现文件中定义。这是非常不好的,因为在更一般的情况下,它冒着使用未初始化变量的风险。这称为“静态初始化顺序失败”,在 C++ FAQ 中进行了讨论。
您应该更改设计并让 main
创建 Julia
实例,而不是这些技术解决方法。
它可以传递给调用的函数。
如果你发现它被传递给了一些函数,特别是作为第一个参数,那么也许这些函数应该是 Julia
class 的成员函数,或者你应该然后为此引入一个新的class。
in complex.h
Julia J;
这是你的错误。 #includes complex.h 的任何源文件都有自己的 J
版本。这违反了 one definition rule.
如果您使用全局变量 J
的唯一地方是在您的 int main
中,则没有理由将该变量设置为全局变量。使 J
成为主函数中的局部变量。声明一个只在一个地方使用的全局变量是错误的。
另一方面,如果您在多个文件中使用该变量,那么您的做法也是错误的。在这种情况下,您的 complex.h
头文件应使用 extern
关键字限定您的变量 J
。现在您可以在多个地方引用该全局变量(但要注意 static initialization fiasco)。您可以在多个地方引用该变量。您需要在一个地方定义该变量。
在您的 class Julia
声明中放置一个 static Julia& GetInstance()
函数(在头文件中)。
在源文件中放置一个 Julia
(Julia J
) 的实例。然后在 GetInstance()
实现中(也在源文件中), return 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; }