我打开了一些编译器警告(C4263和C4264)并发现了这个错误:
class tCommand
{
...
};
class tTestModule
{
public:
virtual bool HandleCommand(tCommand&) { return false; }
}
class tCommandADCReadings : public tCommand
{
...
};
class tADCReadings : public tTestModule
{
public:
tADCReadings();
bool HandleCommand(tCommandADCReadings&);
}
bool tADCReadings::HandleCommand(tCommandADCReadings& cmd)
{
...
}
这会显示警告,因为tADCReadings::HandleCommand()
的实施与tTestModule::HandleCommand()
不匹配。所以我修理了这个:
class tADCReadings : public tTestModule
{
public:
tADCReadings();
bool HandleCommand(tCommand&) override;
}
bool tADCReadings::HandleCommand(tCommand& cmd)
{
tCommandADCReadings* pCmdADCReadings = dynamic_cast<tCommandADCReadings*>(&cmd);
}
但是另一位团队成员说我们应该保留使用tCommandADCReadings
中的tADCReadings::HandleCommand()
给我们的类型检查,所以只需删除tTestModule::HandleCommand()
即可。但是这个函数也被用在~10个其他子类中,所以看起来很遗憾。还有另一种方法可以保持virtual
并确保编译时类型正确吗?
答案 0 :(得分:1)
“还有另一种方法来保持虚拟并确保编译时类型正确吗?”答案取决于您如何在其余代码中使用tCommand对象。假设您的代码类似于:
typedef std::vector<std::shared_ptr<tTestModule>> module_list;
bool handle(tCommand& c, module_list const& m)
{
bool fin = false;
for (auto i = m.begin(), e = m.end(); i != e && !fin; ++i)
fin = (*i)->HandleCommand(c);
return fin;
}
在这种情况下,您有一个未知最终类型的tCommand对象,该对象被传递给各种未知最终类型的tTestModule对象。在这种情况下,答案是否定的。您不能使用两种未知类型进行运行时调度和编译时间类型安全。
要获得编译时安全性,您需要至少知道其中一种类型,如下所示:
template <class C>
bool handle(C& c, module_list const& m)
{
bool fin = false;
for (auto i = m.begin(), e = m.end(); i != e && !fin; ++i)
fin = (*i)->HandleCommand(c);
return fin;
}
但是对于类型安全,你实际上需要在tTestModule中为从tCommand派生的每个类型重载HandleCommand()。如果您还可以在编译时知道m中模块的类型(即通过值使用std :: tuple模块而不是参考模块的向量),那么您将具有类型安全性而不会出现过载问题。