我正在尝试创建和使用成员函数指针的unordered_map,作为接口的一部分,由子类继承和使用。最终目标是允许脚本使用子类(“可编写脚本”),以便可以通过文本“命令”调用它们的函数。
我遇到了语法问题,以及涉及成员函数指针及其继承和使用的困难。我尝试了很多变化,但这是一个复杂而微妙的问题,正如我的谷歌搜索给我看到的那样。
界面:
#include <string>
#include <vector>
#include <unordered_map>
#include <functional>
using namespace std;
class IScriptable
{
public:
virtual void Init() = 0;
bool Run_Script_Command(string i_Command, vector<string> i_Arguments);
protected:
void Register_Command_Function_Pair(string i_Command, function<void(const IScriptable&, vector<string>)> i_Function);
unordered_map<string, function<void (const IScriptable&, vector<string>)>> m_Command_Functions;
};
bool IScriptable::Run_Script_Command(string i_Command, vector<string> i_Arguments)
{
if (m_Command_Functions.find(i_Command) != m_Command_Functions.end())
{
(m_Command_Functions[i_Command])(*this, i_Arguments);
}
else
{
return(false);
}
return(true);
}
void IScriptable::Register_Command_Function_Pair(string i_Command, function<void(const IScriptable&, vector<string>)> i_Function)
{
m_Command_Functions[i_Command] = i_Function;
}
子对象:
class Child : public IScriptable
{
public:
virtual void Init();
protected:
void Foo(vector<string> parms); // The function I'm going to try and add and invoke later
};
void Child::Init()
{
Register_Command_Function_Pair("TestFunction", &Child::Foo);
}
void Child::Foo(vector<string> parms)
{
cout << "Calling Foo\n";
for (vector<string>::iterator it = parms.begin(); it != parms.end(); it++)
{
cout << *it;
cout << "\n";
}
}
代码使用示例:
int main()
{
Child c;
c.Init();
vector<string> arguments;
arguments.push_back("Testing");
arguments.push_back("123");
c.Run_Script_Command("TestFunction", arguments);
// Expected output:
// Calling Foo
// Testing
// 123
}
我试图创建一个我正在尝试做的简化示例,所以希望我的目标有意义,即使有一些其他糟糕的设计决策(为了示例而制作)。
如何编译并给出预期的输出?
感谢。
编辑:上面的代码应抛出以下编译器错误:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(506): error C2664: 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Set(std::_Func_base<_Ret,const IScriptable &,std::vector<_Ty,std::allocator<_Ty>>> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>> *'
with
[
_Ret=void
, _Ty=std::string
]
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Do_alloc<_Myimpl,_Fret(__cdecl Child::* const &)(std::vector<_Ty,std::allocator<_Ty>>),_Alloc>(_Fty,_Alloc)' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
, _Alloc=std::allocator<std::_Func_class<void,const IScriptable &,std::vector<std::string,std::allocator<std::string>>>>
, _Fty=void (__cdecl Child::* const &)(std::vector<std::string,std::allocator<std::string>>)
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Do_alloc<_Myimpl,_Fret(__cdecl Child::* const &)(std::vector<_Ty,std::allocator<_Ty>>),_Alloc>(_Fty,_Alloc)' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
, _Alloc=std::allocator<std::_Func_class<void,const IScriptable &,std::vector<std::string,std::allocator<std::string>>>>
, _Fty=void (__cdecl Child::* const &)(std::vector<std::string,std::allocator<std::string>>)
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Reset_alloc<_Fret,Child,std::vector<_Ty,std::allocator<_Ty>>,std::allocator<std::_Func_class<_Ret,const IScriptable &,std::vector<_Ty,std::allocator<_Ty>>>>>(_Fret (__cdecl Child::* const )(std::vector<_Ty,std::allocator<_Ty>>),_Alloc)' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
, _Alloc=std::allocator<std::_Func_class<void,const IScriptable &,std::vector<std::string,std::allocator<std::string>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Reset_alloc<_Fret,Child,std::vector<_Ty,std::allocator<_Ty>>,std::allocator<std::_Func_class<_Ret,const IScriptable &,std::vector<_Ty,std::allocator<_Ty>>>>>(_Fret (__cdecl Child::* const )(std::vector<_Ty,std::allocator<_Ty>>),_Alloc)' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
, _Alloc=std::allocator<std::_Func_class<void,const IScriptable &,std::vector<std::string,std::allocator<std::string>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Reset<void,Child,std::vector<_Ty,std::allocator<_Ty>>>(_Fret (__cdecl Child::* const )(std::vector<_Ty,std::allocator<_Ty>>))' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,const IScriptable &,std::vector<std::string,std::allocator<_Ty>>>::_Reset<void,Child,std::vector<_Ty,std::allocator<_Ty>>>(_Fret (__cdecl Child::* const )(std::vector<_Ty,std::allocator<_Ty>>))' being compiled
with
[
_Ret=void
, _Ty=std::string
, _Fret=void
]
Source\GoDatabase.cpp(3436) : see reference to function template instantiation 'std::function<void (const IScriptable &,std::vector<std::string,std::allocator<_Ty>>)>::function<void(__cdecl Child::* )(std::vector<_Ty,std::allocator<_Ty>>)>(_Fx &&)' being compiled
with
[
_Ty=std::string
, _Fx=void (__cdecl Child::* )(std::vector<std::string,std::allocator<std::string>>)
]
Source\GoDatabase.cpp(3436) : see reference to function template instantiation 'std::function<void (const IScriptable &,std::vector<std::string,std::allocator<_Ty>>)>::function<void(__cdecl Child::* )(std::vector<_Ty,std::allocator<_Ty>>)>(_Fx &&)' being compiled
with
[
_Ty=std::string
, _Fx=void (__cdecl Child::* )(std::vector<std::string,std::allocator<std::string>>)
]
答案 0 :(得分:0)
您的功能类型应为:
std::function<void(std::vector<std::string>)>
const IScriptable&
在那里不起作用,如果你想使用指针方法,那将是完全不同的语法。
然后Init()
就是这样:
using namespace std::placeholders;
Register_Command_Function_Pair("TestFunction", std::bind( &Child::Foo, this, _1 ) );
Run_Script_Command()
变为:
bool IScriptable::Run_Script_Command(string i_Command, vector<string> i_Arguments)
{
auto f = m_Command_Functions.find(i_Command);
if ( f != m_Command_Functions.end())
{
f->second(i_Arguments);
return true;
}
return false;
}
请注意,您应该为正在使用的typedef
创建类型别名(using
或std::function
),因为您多次使用它。这将使代码更具可读性,并且更容易更改该类型。