【问题标题】:How to share a global class instance between files?如何在文件之间共享全局类实例?
【发布时间】:2019-10-08 18:42:04
【问题描述】:

我有一个类 myClass,它被分成一个 .h 和 .cpp 文件。然后我有一个 main.cpp 文件,我在其中声明了一个 myClass 的全局实例

myClass class1(0,0);

我还有一些使用 class1 的其他 cpp 文件,例如 Funcs.cpp。因此,我创建了一个 extern 文件 extern.h,并将 myClass 实例也声明为 extern:

extern myClass class1;

myClass 有两个可用的构造函数,一个接受两个参数,另外三个(重载)。没有不接受参数的构造函数。有两个参数的构造函数是这样的:

myClass:myClass(int id, int mode);

我的问题是我收到以下错误消息:

标识符 myClass 未定义“extern myClass class1”

...尽管我在 main.cpp、myClass.cpp 和 extern.h 中都包含了 myClass.h。

在多个 cpp 文件之间共享 myClass 的全局实例的正确方法是什么?我通读了Issue declaring extern class object,不同之处在于 myClass 有两个参数,并且我的全局实例是在 main.cpp 而不是 myClass.cpp 中声明的。

【问题讨论】:

  • 正确的方法是不要使用全局实例。如果其他一些实例或函数需要class1(顺便说一句不是最好的名称),则将其传递给他们。顺便说一句,不要考虑“cpp 文件”。你可以将所有代码放在一个文件中,它仍然会做同样的事情(当然有一些例外)。
  • 表面问​​题是你的类的'用户'需要访问全局变量的声明myclass的完整声明,即头文件必须同时包含两者。全局变量的实际定义 可以在某处进入单个.cpp 文件。 singleton pattern 体现了底层问题(如何安全地定义全局变量)。
  • 你能粘贴一个非常精简的文件吗?
  • 应该可以。向我们展示您的minimal reproducible example

标签: c++ class extern c++98


【解决方案1】:

问题可能是包含文件的顺序。编译器会信任地逐行处理每个编译单元,包括#include 位置的.h 文件的内容。

这意味着您必须在 extern.h 之前包含 myclass.h:

#include "myclass.h"
#include "extern.h"

【讨论】:

  • 实际上,如果这是问题,他应该从“extern.h”中包含“myclass.h”,这样他就再也不会遇到问题了,但是问题表明他已经包含了这些。跨度>
  • @xception:我学会了永远不要包含其他包含文件,除非使用#ifndef __SOME_UNIQUE_ID #define __SOME_UNIQUE_ID content of file #endif仔细保护多个包含文件
  • 这对我帮助很大。我在“myClass.h”中包含了“extern.h”,这就是为什么“extern.h”首先被执行的原因。删除它,错误确实消失了!谢谢。
【解决方案2】:

您的需求的一个非常精简的版本应该可以工作:

myclass.h:

#ifndef MYCLASS_H
#define MYCLASS_H

class myClass
{
public:
        myClass(int, int);
};

#endif // MYCLASS_H

extern.h:

#ifndef EXTERN_H
#define EXTERN_H

#include "myclass.h"
extern myClass class1;

#endif // EXTERN_H

使用extern.cpp:

#include "extern.h"

bool variable_named_class1_exists()
{
        return (bool)&class1;
}

在更现代的 C++ 版本/使用现代编译器时,我更喜欢 #pragma once 作为保护而不是 #ifndef UNIQUE_ID、#define UNIQUE_ID、#endif 组合,因为对于更大的项目,很难不结束与“UNIQUE_ID”发生冲突。

【讨论】:

  • “对于一个更大的项目,真的很难不发生碰撞” 不应该。请注意,#pragma once 与“现代版本的 C++”无关,因为它在定义上是非标准的。
  • 最好不要将实例称为“类”。 object1 也许。不管这是 OP 已经声称拥有的代码,所以我们应该等待找出真正的问题是什么。
  • @LightnessRacesinOrbit 重命名函数以更明确地说明它的作用,无法重命名 var 因为 OP 说他已经命名了这样的变量。
【解决方案3】:

虽然使用这样的全局变量完全合法,但它更像是 C 代码,而不是 C++ OOP。然后你应该考虑让它成为你类的静态成员。如果你认为它在你的上下文中意义不大,那么这意味着你的变量可能也不应该是全局的。

如果您将其设为静态成员,它将解决您的问题,因为您只需要包含声明您的类型的标头。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多