在不发布大量代码的情况下,这对我来说会有点复杂,但我会尽力而为。我正在编写一个游戏内控制台,它要求我将正常的免费函数和实例方法绑定到控制台,以便可以使用简单的关键字调用它们。控制台可以绑定的每个方法/函数都需要一个 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 循环。我已经检查过了。
我在网上做了一些谷歌搜索,但我从来没有发现像这样的链接器错误。它总是关于忘记包含或包含循环。
有谁知道我做错了什么,以及如何解决?感谢您花时间阅读本文,并提前感谢您的任何回复。- 洛根