2017-09-27 65 views
0

我打开了一些编译器警告(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); 
} 

但其他小组成员说,我们应该保持的类型检查,在tADCReadings::HandleCommand()使用tCommandADCReadings给我们,所以才删除tTestModule::HandleCommand()。但是这个函数在〜10个其他的子类中也被使用,所以这似乎是一个耻辱。有没有其他方法来保持virtual并确保编译时类型的正确性?

+0

其他函数是否使用与基类相同的签名,或者其他函数是否也在更改参数类型?如果签名发生变化,那么我没有看到在基类中声明虚函数的好处。 另外,通过更改签名,您不会覆盖基类的函数。您发现的警告是告诉您,具有这两种功能可能会导致所谓的混淆。 –

+0

有没有人真的调用过'tTestModule :: HandleCommand'?如果他们这样做,由于没有任何东西似乎覆盖它,命令将无法处理,并且该调用可能是可移除的。否则,您可以在子类中创建覆盖,在这些子类中执行'dynamic_cast',如果动态转换成功,则调用超类的'HandleCommand'。 – 1201ProgramAlarm

回答

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; 
} 

在这种情况下,你必须传递到各种tTestModule对象还未知最后一种类型的未知最终类型的tCommand对象。在这种情况下,答案是否定的。你不能有两种未知类型的运行时分派和编译时间类型安全。

要获得编译时的安全,你需要知道参与作为类型中的至少一个如下:

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 HandleCommand()派生所有类型来自tCommand。如果你也可以在编译时知道m的模块类型(例如,通过值来代替模块的向量来使用std :: tuple模块),那么你可以在没有超载头疼的情况下输入安全类型。