gthr-default.h 中的多重定义

Multiple definition in gthr-default.h

所以我在头文件中这样做 gui_base.hpp "gui_flags" 只是位标志的定义, nsp_input 需要访问 "handle mouse" 中的变量 在 gui_text.hpp 中,我声明文本块 class。 每个 "gui_" 文件都在 GUI:: 命名空间中。

#ifndef _GUI_BASE_HPP_
#define _GUI_BASE_HPP_

#include "gui_flags.hpp"
#include "nsp_input.hpp"
#include "gui_text.hpp"


class GUI::base
{
protected:
  struct s_lastclick
  {
    float ltime,rtime;
    glm::vec2 pos;
    bool rc, lc, first;
  };

  std::string m_name;

  float m_width;
  float m_height;

  glm::vec2 m_center;
  glm::mat2x2 m_tlbr;

  GUI_FLAGS m_flags;

  s_lastclick m_lastclick;
  textblock m_textblock;



  std::map<std::string, std::shared_ptr<base>> m_slaves;

  glm::vec4 color;

public:
  base(std::string gn, float &gw, float &gh, glm::vec2 &gc);

  bool check_borders();

  void move(glm::vec2 &gpos);
  void move(float &x, float &y);

  void toggle_flags(GUI_FLAGS f);
  void open();
  void close();

  void set_color(glm::vec3 &color);
  void set_transparency(float &t);

  void enslave(std::string name, std::shared_ptr<base> &gslave);
  void free_slave(std::string name);
  void check_slaves();

  void add_text(std::string text, glm::vec2 position, glm::vec3 color,
                GLfloat scale=1.0f, GLfloat padx=8.0f, GLfloat pady=8.0f);

  virtual void handle_mouse();
  virtual void handle_keys();

};

#endif // _GUI_BASE_HPP_

如果需要更多细节,我可以在这里复制它们,我只是不想垃圾邮件太多代码。

编译器简单地给出了两个错误:

obj\Debug\Sources\gui_base.o:c:\mingw\lib\gcc\mingw32.3.0\include\c++\mingw32\bits\gthr-default.h|402|first defined here|

||error: ld returned 1 exit status|

||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

所有变量和函数都在gui_base.cpp中定义(包括虚拟变量和函数)。 我或多或少将它转移到 "into" 命名空间,因为我让它在全局命名空间中作为 "normal" class 工作就好了,所以我认为它与它有关。但是鉴于我缺乏经验,编译器错误提供的少量(对我而言)可理解的信息让我有点不知所措。

我能找到的大多数条目都是关于头文件中定义的多个定义错误,根据我的理解,我的头文件中没有。

这里是 gui_base.cpp:

#include "../Headers/gui_base.hpp"

namespace input_handler
{
  std::unique_ptr<s_mouse> up_mouse;
  std::map<uint32_t, bool> KEYS;
}

GUI::base::base(std::string gn, float &gw, float &gh, glm::vec2 &gc) : m_name(gn),
                                                                          m_width(gw),
                                                                          m_height(gh),
                                                                          m_center(gc)
{
  resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}

void GUI::base::handle_keys()
{

}
void GUI::base::handle_mouse()
{

}
bool GUI::base::check_borders()
{
  if(input_handler::up_mouse->position.x > m_tlbr[0].x &&
     input_handler::up_mouse->position.y < m_tlbr[0].y &&
     input_handler::up_mouse->position.x < m_tlbr[1].x &&
     input_handler::up_mouse->position.y > m_tlbr[1].y)
      return true;
  else
    return false;
}

void GUI::base::move(glm::vec2 &gpos)
{
  m_center = gpos;
  resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}

void GUI::base::move(float &x, float &y)
{
  m_center = glm::vec2(x,y);
  resource_manager::calc_tlbr(m_tlbr, m_center, m_width, m_height);
}

void GUI::base::enslave(std::string name, std::shared_ptr<base> &gslave)
{
  m_slaves[name] = gslave;
}

void GUI::base::check_slaves()
{
  for(auto iter : m_slaves)
  {
    if(iter.second->check_borders())
    {
      if(iter.second->m_flags & GUI_OPEN)
        iter.second->check_slaves();
    }
    else
      continue;
  }
}

void GUI::base::open()
{
    toggle_flags(GUI_OPEN | GUI_DRAW | GUI_CLOSED);
    if(!m_slaves.empty())
    {
        for(auto iter : m_slaves)
        {
            iter.second->open();
        }
    }

}

void GUI::base::toggle_flags(GUI_FLAGS f)
{
  m_flags ^= f;
}

void GUI::base::close()
{
    toggle_flags(GUI_OPEN | GUI_DRAW | GUI_CLOSED);
    if(!m_slaves.empty())
    {
        for(auto iter : m_slaves)
        {
            iter.second->close();
        }
    }
}
void GUI::base::add_text(std::string text, glm::vec2 position, glm::vec3 color,
                GLfloat scale, GLfloat padx, GLfloat pady)
{
  m_textblock = GUI::textblock(position, color, scale, padx, pady, text);
}

编辑: 我的 class 在 nsp_gui.hpp 文件中声明,该文件包含在 gui_text.hpp 文件中(包含在有关 gui_base 文件中)

我声明我的 class 如下:

#ifndef _NSP_GUI_HPP_
#define _NSP_GUI_HPP_

namespace GUI
{
  //the renderer class
  class renderer;
  class base;
  class window;
  //init function -> text will be in the GUI
  extern void init_gui();
}

#endif // _NSP_GUI_HPP_

都怪我 - 我在构建日志中发现了这个(不知道有一个..抱歉):

obj\Debug\Sources\gui_text.o:gui_text.cpp:(.bss+0x0): multiple definition of GUI::textblock_storage[abi:cxx11] obj\Debug\Sources\gui_base.o:gui_base.cpp:(.bss+0x0): first defined here obj\Debug\Sources\gui_window.o:gui_window.cpp:(.bss+0x0): multiple definition of GUI::textblock_storage[abi:cxx11]

我在 gui_text.hpp 中声明的文本块存储: (gui_window "simply" 继承自 gui_base,所以这可能就是它出现在那里的原因)

#ifndef _GUI_TEXT_HPP_
#define _GUI_TEXT_HPP_

#include "nsp_rmng.hpp"
#include "nsp_gui.hpp"
#include <ft2build.h>
#include FT_FREETYPE_H

namespace GUI
{
  extern void init_alphabet();
  extern void write();
  class textblock
  {
  public:
    glm::vec2 position;
    glm::vec4 instancing;
    glm::vec3 color;
    GLfloat scale, padx, pady;
    std::string text;
    void calc_offsets();
    textblock(){};
    textblock(glm::vec2 &p, glm::vec3 &c,
                GLfloat &s, GLfloat &px, GLfloat &py,
                std::string &t);

  };
  std::map<std::string, textblock> textblock_storage;
}

#endif // _GUI_TEXT_HPP_

奇怪的是我没有在任何地方定义它。我还没有在 base 和 text.cpp 中使用它,尽管我想在 gui_text.cpp 中使用它。那不应该只是一个未知的引用吗?

obj\Debug\Sources\gui_base.o:c:\mingw\lib\gcc\mingw32.3.0\include\c++\mingw32\bits\gthr-default.h|402|first defined here|

这不是错误信息。

命名空间 GUI 中的

Class class base 应该像下面这样声明

namespace GUI {
class base {
  ...
};
} // namespace GUI

并且定义也应该在命名空间中。

namespace GUI {
base::base(std::string gn, float &gw, float &gh, glm::vec2 &gc) {
  ...
}
} // namespace GUI

更新 在 OP 编辑​​他的答案后。

The strange thing is that I do not define it anywhere.

您在header中定义了变量textblock_storage,header至少包含了两次,因此变量在obj-files中出现了多次。在下面的 header 中声明它

extern std::map<std::string, textblock> textblock_storage;

并且只在一个 .cpp 文件中定义一次

std::map<std::string, textblock> textblock_storage;