C++ 将静态成员函数作为参数传递时未定义的引用

C++ 将静态成员函数作为参数传递时未定义的引用,c++,glfw,C++,Glfw,我试图在类游戏中设置glfw错误和键回调函数。执行此操作时,我会得到对回调函数的未定义引用 以下是本课程的相关部分: namespace TGE { class Game { public: void init() { glfwSetErrorCallback(error_callback) if(!glfwInit())

我试图在类游戏中设置glfw错误和键回调函数。执行此操作时,我会得到对回调函数的未定义引用

以下是本课程的相关部分:

namespace TGE
{
    class Game
    {
        public:
            void init()
            {
                glfwSetErrorCallback(error_callback)

                if(!glfwInit())
                    exit(EXIT_FAILURE);

                window = glfwCreateWindow(800, 600, "Test", NULL, NULL);

                if(!window)
                {
                    glfwTerminate();
                    exit(EXIT_FAILURE);
                }

                glfwMakeContextCurrent(window);
                glfwSetKeyCallback(window, key_callback);

                start();
            }

            void start()
            {
                // Main loop stuff
            }

            static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
            {
                if(action == GLFW_PRESS)
                {
                    switch(key)
                    {
                        case GLFW_KEY_ESCAPE:
                            glfwSetWindowShouldCLose(window, GL_TRUE);
                            break;
                    }
                }
            }

            static void error_callback(int error, const char* description)
            {
                fputs(description, stderr);
            }

        protected:
            GLFWwindow* window;
    }
}
当我尝试编译时,我得到

In function `TGE::Game::init()`:
undefined reference to `TGE::Game::error_callback(int, char const*)`
undefined reference to `TGE::Game::key_callback(GLFWwindow*, int, int, int, int)`
我有一种感觉,这可能是因为名称空间,但如果是这样,我不知道如何绕过它


编辑:将所有内容移出名称空间会导致相同的错误。

我认为这是因为您对
error\u回调(…)
key\u回调(…)
的定义在
init()
函数之后,两者都使用

编辑:
忽略这一点,这不是原因,因为这是一个链接器错误(请参见下面的注释)

我怀疑这里发生的事情是您在类声明中定义了静态成员函数,这使得它们隐式地
内联
。由于某些编译器错误(甚至可能是标准指定的行为?),编译器没有实例化这些函数的非内联版本,这些函数实际上具有地址和全局符号

无论这种行为是否正确,内联函数只作为通过指针的回调函数,无论如何都是胡说八道。所以它为什么不起作用是没有意义的。通过指针进行的函数调用不是内联的

您应该只在类声明中声明这些函数,然后在某个地方实现它们

// inside the class decl:
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
以及:

确保已编译并链接此文件

但是,下面的测试程序为我编译并链接了g++4.6.3

#include <stdlib.h>
#include <stdio.h>

// Wrapping the class in a namespace makes no difference, by the way.
class test {
  int x[42];
public:
  test()
  {
    qsort(x, 42, sizeof x[0], compare);
  }
  static inline int compare(const void *, const void *)
  {
    return 0;
  }
};

int main(void)
{
  test t;
  return 0; 
}
#包括
#包括
//顺便说一句,将类包装在命名空间中没有任何区别。
课堂测试{
int x[42];
公众:
测试()
{
qsort(x,42,sizeof x[0],比较);
}
静态内联整数比较(常量void*,常量void*)
{
返回0;
}
};
内部主(空)
{
试验t;
返回0;
}

您是否尝试过将回调函数移到使用它们的函数上方?似乎您已经对其进行了排序(下面的回答中有注释),但如果您仍然患有代码盲症-您需要在
glfwSetErrorCallback(error\u callback)
之后使用分号“^缺少分号意味着代码无法编译,这意味着它不是真正的代码。我没有在实现中声明函数Game::key\u callback和Game::error\u callback。愚蠢的错误。我猜这就是一夜没睡之后发生的事。虽然现在我有新的错误要修复,但这仍然有效。如果你没有声明它们,程序是如何进入链接阶段的?问题实际上是,在游戏类的头部,我声明了函数key\u callback和error\u callback,但在.cpp中,我只编写了静态void key\u callback,而不是静态void game::key\u callback。由于函数是在游戏范围内声明的,编译器在那里查找它们,而实现不在游戏范围内,因此导致了未定义的引用。有趣的是,我在编译时必须使用-fppermissive,因为gcc不允许我声明成员函数具有静态链接。这个错误到底意味着什么?为什么,如果我可以在编译器中允许这个,并且一切都很好,它是否应该首先抛出一个错误?@ USER 941616-你不应该把C++函数、C++名字、函数等作为C函数或函数指针传递给C函数,比如GLFW之类的C库。它可能适用于静态方法,因为没有对象被传递,ABI可能使用与C函数相同的调用约定-但这不是您可以依赖的行为。@BrettHale这不是一种可移植性可以依赖的行为,但它是可以验证在给定平台上工作的行为之一,例如,在对象指针和(正则)函数指针之间转换。@卡兹-典型的方法是将C++静态方法调用封装在一个函数中,使用代码>外部“C”< /C>链接,并将其用作回调。
#include <stdlib.h>
#include <stdio.h>

// Wrapping the class in a namespace makes no difference, by the way.
class test {
  int x[42];
public:
  test()
  {
    qsort(x, 42, sizeof x[0], compare);
  }
  static inline int compare(const void *, const void *)
  {
    return 0;
  }
};

int main(void)
{
  test t;
  return 0; 
}