多重定义,如何原型化std::map

multiple definitions, how to prototype std::map?

本文关键字:原型 std map 定义 何原型      更新时间:2023-10-16

我知道发生了什么,但我不知道如何解决这个问题:

主.cpp

#include "Win32.h"
int main () {
    return 0;
}

赢32.h

#include <windows.h>
#include <map>
#ifndef WIN32_H_
#define WIN32_H_
namespace W32 {
class Win32;                        // Pre-Declaration
std::map<HWND, Win32 *> windowMap;  // Handle to Class instance mapping
class Win32 {
    public:
        Win32();
        virtual ~Win32();
    protected:
    private:
};  // Class Win32
} // namespace W32
#endif // WIN32_H_

Win32.cpp

#include "Win32.h"

namespace W32 {
Win32::Win32() {
}
Win32::~Win32() {
}
} /* namespace W32 */

错误消息:

    srcWin32.o: In function `Win32':
    D:DevProjectsEclipseOpenGL3Debug/../src/Win32.cpp:7: multiple definition of `W32::windowMap'
    srcmain.o:D:DevProjectsEclipseOpenGL3Debug/../src/main.cpp:14: first defined here

好的,我知道std::map<HWND, Win32 *> windowMap;出现在多个文件中,并且因为它包含在多个文件(main.cpp/Win32.cpp)中,因此导致它被重新定义。 我对std::map还是有些陌生。 我需要做的是原型windowMap,但我不知道的是怎么做? 我以为这是我抓住这段代码的时候。 Win32 类需要能够使用它,但必须声明它才能这样做,但我拥有的不是这样做的方法,我不知道要寻找什么才能获得有关如何正确转发声明std::map<HWND, Win32 *> windowMap的正确信息。

std::map<HWND, Win32 *> windowMap; 

是一个定义,所以你打破了一个定义规则。您需要将变量设为extern

extern std::map<HWND, Win32 *> windowMap; 

并在单个实现文件中定义它:

赢32.h

#include <windows.h>
#include <map>
#ifndef WIN32_H_
#define WIN32_H_
namespace W32 {
   class Win32;                        // Pre-Declaration
   extern std::map<HWND, Win32 *> windowMap;  // Handle to Class instance mapping
   //...
};  // Class Win32
} // namespace W32
#endif // WIN32_H_

Win32.cpp

#include "Win32.h"
namespace W32 {
   std::map<HWND, Win32 *> windowMap;  // Handle to Class instance mapping
   //...
} /* namespace W32 */

以下是一个定义,而不是一个声明

std::map<HWND, Win32 *> windowMap;

定义在 cpp 文件中;在标头中,您需要一个声明,如下所示:

extern std::map<HWND, Win32 *> windowMap;

定义

std::map<HWND, Win32 *> windowMap;

应该进入 cpp 文件。否则,每个包含带有定义的标头的 cpp 文件都将定义自己的windowMap ,从而导致您看到的链接器错误。

纯C++方法是使:

std::map<HWND, Win32 *> windowMap"

Win32 类的static成员。此外,忘记file.hfile.cpp,为了简单起见,几乎每个铁杆开发人员都弃用了它。你的代码太短了,所以所有内容都应该包含在标题中,尤其是在像你这样对框架进行编程时。

您的问题弹出了静态成员存在于C++的原因。此外,定义此地图extern不是好的做法,因为您还必须将真正的定义隐藏在某个地方,也许在不那么相关的地方。

最后,我已经尝试过这种设计,Windows 处理程序的函数以异步方式调用......

1- 如果多个窗口同时处于活动状态,您将在竞争条件下运行。

2-实际上,一旦调用该函数,您就会运行竞争条件CreateWindow因为它会在您的背后调用您的Windows消息泵处理程序,并且您还不知道HWND

3-如果您尝试同时在地图中insert/read/remove,您将运行竞争条件,这实际上是一种非常常见的操作。