【问题标题】:In C++, how to use a singleton from a separate source file?在 C++ 中,如何使用来自单独源文件的单例?
【发布时间】:2011-11-22 23:22:57
【问题描述】:

我正在尝试在一个大型系统上编译一些其他人的包装程序,其中它使用来自另一个文件的全局对象,该类的定义如下:

class __declspec(dllexport) A
{
...
static A * instance;
}

在我单独的源文件(我想将其构建为 .exe)中,我包含了头文件 A.h,并在开头这样声明

A * A::instance;

访问A中的数据。

问题是,这段代码可以在Linux上成功构建,现在我尝试在windows NT下构建,就会出现问题。

  1. 如果我这样处理,编译器会报错C2491 error, definition of dllimport function not allowed

  2. 如果我删除这行 A 声明,我会收到很多错误LNK2001: unresolved external symbol

不太清楚这里的问题是什么,我在网上做了一些研究,但找不到一个好的答案,我自己也不太熟悉 dll 导入/导出和一些 C++ 技巧。谁能提供一些关于这个问题的见解或者我应该花时间在哪个方向来解决这个问题?

或者说,如果我已经有一个这样的静态对象,并且我想编写另一个程序来访问它,我应该怎么做?

如果我在这里犯了任何错误,还请纠正我。谢谢!

【问题讨论】:

  • 您不能在 C 程序中使用 class - 所以您的问题让我们感到困惑(如果不是您自己的话)。我已经对不会造成大混乱的措辞进行了修复。您可能希望将“.c”文件的后缀更改为 C++ 后缀 - 但我不确定 Windows 上的后缀是哪个。在 Unix 上,您可以使用 .C.cxx.cpp 作为后缀。
  • 嗯,谢谢指正。但我现在有点困惑,对我来说它只是从 .c 或 .C 构建一个 .exe,它基于 C++ 系统,已经有几个类似的 .exe 像这样构建,并且在两者上都可以正常工作linux和windows。后缀在这里真的很重要吗?
  • 旁注:您可能想知道单例被认为是一种反模式(请参阅wikipedia),因此请尽量避免使用它
  • 在机器上不知道,但你需要在 SO 上区分 C 代码和 C++ 代码,否则人们会像一吨砖一样跳到你身上——比我做的要难得多。最初,您的标题是“单独的 C 文件”,但您做的第一件事是包含一个不是有效 C 代码的标头。不要混淆两种语言;它们是不同的。
  • 我明白了,我想我正在制作一个 C 程序但依赖于 C++ 系统,这是正确的说法吗?

标签: c++ visual-studio dll dllimport


【解决方案1】:

我认为你需要的关键字是extern,如:

extern A *A::instance;

这表示变量 A::instance 是在其他地方定义的,但您将它告诉编译器,以便您可以在此文件中按名称使用它。

【讨论】:

  • 是的,我忘了在我的帖子中提到我试过了,正是你的建议,但会得到一个错误 'error C2720: 'A::instance' : 'extern ' storage-class specifier对会员违法
【解决方案2】:

__declspec(dllexport) 用于将函数导出到 DLL 中。只要您不从另一个 DLL 调用该类,就不需要它。

但我怀疑您的问题与使用 .c 文件有关,而不是与类规范有关。顺便读一下。它非常详细地讨论了 dllexport Windows & C++: extern & __declspec(dllimport)

【讨论】:

    【解决方案3】:

    单例通常有一个函数,比如

    A::instance = NULL;
    A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
    

    如果您有这样的函数,则不必直接访问 A::instance。

    对不起,你在做什么?在 C 程序中包含 C++ 头文件?它甚至可以编译吗?

    【讨论】:

      【解决方案4】:

      就我个人而言,我通常将实例隐藏在匿名命名空间中的 .cpp 文件中。然后我提供了一个 getInstance() 函数,它返回一个指针或对它的引用,然后我 dllExport 该函数。

      如果您想强制执行某些操作,可以将 A 的构造函数设为私有,并将 getInstance 设为好友。

      【讨论】:

        猜你喜欢
        • 2015-05-22
        • 2019-10-27
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 2013-07-03
        • 2017-12-11
        相关资源
        最近更新 更多