0

在不发布大量代码的情况下,这对我来说会有点复杂,但我会尽力而为。我正在编写一个游戏内控制台,它要求我将正常的免费函数和实例方法绑定到控制台,以便可以使用简单的关键字调用它们。控制台可以绑定的每个方法/函数都需要一个 sf::String 参数,并返回一个 sf::String。(我在游戏中使用 SFML,sf 是 SFML 的命名空间)

[注意:所有 4 个类(Console、CFunctionInterface、CFunction 和 CMethod)都在同一个文件(console.h)中声明。它们的成员都定义在一个文件中(console.cpp)]

为了进行设置,我有 1 个父级 (CFunctionInterface) 和 2 个子级 (CFunction, CMethod) 'container' 类。父级内部有 1 个公共方法。

sf::String call(sf::String p_Value);

CFunction 的声明如下所示:

class CFunction : public CFunctionInterface
{
public:
    typedef sf::String (*FFP)(sf::String);  //free function pointer type

    CFunction(const FFP p_Function);
    sf::String call(const sf::String p_Value);
private:
    FFP m_Function;
};

CMethod 的声明如下所示:

template <typename ClassType>
class CMethod : public CFunctionInterface
{
public:
    typedef sf::String (ClassType::*MFP)(sf::String);   //member function pointer type

    CMethod(const ClassType* p_Instance, const MFP p_Function);
    sf::String call(const sf::String p_Value);
private:
    ClassType* m_Instance;
    MFP m_Function;
};

一切都是不言自明的,我相信你可以想象 call() 对每个类做了什么。

回到控制台,我有一个

std::multimap <string, CFunctionInterface* > 

设置为存储所有函数指针。当我想调用一个函数时,这个映射将被迭代,如果输入的函数名称与其中一个键匹配,则该键的值将被调用。例如(名称是所需函数的所需键,参数是我要传递给函数的 sf::String [push_back() 是向控制台输出消息的控制台方法]):

for(auto iter = functions.begin(); iter!= functions.end(); iter++)
{
    if(iter->first == name)
    {
        push_back(iter->second->call(param));
        return;
    }
}
push_back("Error! Function with name: " + name + " not found!");

现在我在控制台中有一些方法,用于绑定和取消绑定功能。这就是问题出现的地方。

template <typename ClassType>
void bindFunction(const string name, const ClassType* instance, sf::String (ClassType::*func)(sf::String));
void bindFunction(const string name, sf::String (*func)(sf::String));
void unbindFunction(const string name);

最后两个函数运行良好。那里没有问题。但就是那个模板混蛋。这是他的定义(console.cpp 内部):

template <typename ClassType>
void CConsole::bindFunction(const string name, const ClassType* instance, sf::String    (ClassType::*func)(sf::String))
{
    //Checks to see if name is already in use
    for(auto iter =  functions.begin(); iter != functions.end(); iter++)
    {
        if(iter->first == name)
        {
            push_back("Error! Attempting to bind function. The name \'" + name + "\' is already in use!");
            return;
        }
    }
    //Everything checks out
    CMethod* temp = new CMethod<ClassType> (instance, func);
    functions.insert( pair<string, CFunctionInterface* > (name, temp) );
}

当我在整个程序中根本不给他打电话时,它编译并运行得很好。但是当我尝试调用它时;我收到此错误:

1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall CConsole::bindFunction<class CDog>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class CDog const *,class sf::String (__thiscall CDog::*)(class sf::String))" (??$bindFunction@VCDog@@@CConsole@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PBVCDog@@P83@AE?AVString@sf@@V45@@Z@Z) referenced in function _main
1>S:\Users\Logan\documents\visual studio 2012\Projects\newConsole\Debug\newConsole.exe : fatal error LNK1120: 1 unresolved externals

这就是在 'int main()' 中调用它的样子:

CDog* rex = new CDog;
console->bindFunction<CDog>("bark", rex, &CDog::bark);

CDog 只是一个简单的类,它带有一个返回“Woof!”的公共 bark() 方法。控制台是在 main 内部创建的,它只是一个指向新 CConsole 对象的指针。包含“console.h”,并且没有#include 循环。我已经检查过了。

我在网上做了一些谷歌搜索,但我从来没有发现像这样的链接器错误。它总是关于忘记包含或包含循环。

有谁知道我做错了什么,以及如何解决?感谢您花时间阅读本文,并提前感谢您的任何回复。- 洛根

4

0 回答 0