使用子类型对虚函数进行子类化

时间:2017-09-27 22:05:19

标签: c++ virtual

我打开了一些编译器警告(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并确保编译时类型正确吗?

1 个答案:

答案 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模块而不是参考模块的向量),那么您将具有类型安全性而不会出现过载问题。