我从下面的代码中得到了错误。怎么了?一切似乎都到位了。
错误C2784:'void Menu :: AddLeaf(Command,const int)':不能 推导出'Command'的模板参数 'LauncherCommandChangeSimulation'
Command.h
template <class Receiver>
class Command
{
virtual void Execute() = 0;
...
};
LauncherCommand.h
#include "Menu/Command.h"
#include "Internal/Launcher.h"
class LauncherCommand : public Command<Launcher>
{ ... };
class LauncherCommandChangeSimulation : public LauncherCommand
{ ... };
Menu.h
template <class T>
class Command;
class Menu
{
public:
template <class T>
void AddLeaf(Command<T> command, const int parentId);
};
Game.cpp
#include "Internal/Launcher.h"
#include "Menu/Menu.h"
#include "Menu/LauncherCommand.h"
LauncherCommandChangeSimulation command(...);
menu.AddLeaf(command, ...); // Error here
如果我在
上更改了对AddLeaf的调用menu.AddLeaf<Launcher>(command, simsNodeId);
然后我得到下一个错误
错误C2770:'void的显式模板参数无效 Menu :: AddLeaf(Command,const int)'
答案 0 :(得分:3)
您尝试将派生类对象传递给按值获取Command
基类的函数。这将尝试切片对象,复制基础子对象并丢弃使其成为LauncherCommand
和LauncherCommandChangeSimulation
的所有内容。即使这样有效,也不会是你想要的;在这种情况下,它不会起作用,因为基类是抽象的,因此无法实例化为完整的对象。
为了在菜单中存储多态对象,您需要某种间接方式。看起来你需要一个非模板的基类,而AddLeaf
需要采用并存储一个(最好是智能的)指针。
答案 1 :(得分:2)
如果通过引用获取command
参数,则它有效。
这是因为§14.8.2.1(4):
通常,演绎过程会尝试查找模板参数值,这些参数值会使推导的
A
与A
相同(在A
类型转换后如上所述)。但是,有三种情况可以产生差异:
- ...
- ...
- 如果
P
是一个类而P
的格式为 simple-template-id ,则转换后的A
可以是推导出的派生类A
。同样,如果P
是指向 simple-template-id 形式的类的指针,则转换后的A
可以是指向推导出的派生类的指针。A
。
但是你需要处理对象的生命周期管理,所以迈克是正确的,你会想要一个智能指针。