使用模板和继承进行设计测试

时间:2014-06-23 09:42:50

标签: c++ templates multiple-inheritance

我对C ++中的设计有疑问。 正如您在下面的代码中看到的那样,存在设计问题。我希望能够拥有一个TestClass,它继承自ModeBase(本例中为ModeOneModeTwo)的零个或多个类。如果TestClass继承自ModeOne,则可以使用MethodeOne()TestClass要求MethodOne()实施class ModeBase { //--Methods-------------------------------------------------------------------- public: virtual ~ModeBase() = default; }; class ModeOne : private ModeBase { //--Methods-------------------------------------------------------------------- public: virtual ~ModeOne() = default; virtual void MethodOne() {} }; class ModeTwo : private ModeBase { //--Methods-------------------------------------------------------------------- public: virtual ~ModeTwo() = default; virtual void MethodTwo() {} }; class TestBase { //--Methods-------------------------------------------------------------------- public: TestBase() : currentMode_( nullptr ) {} virtual ~TestBase() = default; template <class Mode, class T> void ChangeMode() { if( std::is_base_of<Mode, T>::value ) { // Class does inherit from Mode so we make sure the current mode // has changed currentMode_ = std::make_shared<Mode>(); } else { // Class does not inherit from Mode so we don't do anything } } template <class Mode> bool CurrentMode() { if( std::dynamic_pointer_cast<Mode>(currentMode_) != nullptr ) { return true; } return false; } //--Data members--------------------------------------------------------------- private: std::shared_ptr<ModeBase> currentMode_; }; class TestOne : public TestBase , private ModeOne , private ModeTwo { //--Methods-------------------------------------------------------------------- ~TestOne() = default; void HeartbeatTick() { if( CurrentMode<ModeOne>() ) { MethodOne(); } else if( CurrentMode<ModeTwo>() ) { MethodTwo(); } } virtual void MethodOne() {} virtual void MethodTwo() {} }; class SomeManager { ~SomeManager() = default; void ChangeAllMode() { for( auto it = vector_.begin(); it != vector_.end(); ++it ) { // Here is the problem with this implementation. I need to know // the type of the TestBase derived class (TestOne) to use it as // a `ChangeMode` method template parameter. //(*it)->ChangeMode<AIModeFollowLine, SOMETYPE>(); } }; std::vector<std::shared_ptr<TestBase>> vector_; }; 这就是我的要求想。

vector_

我已经知道这是糟糕的设计,因为ChangeMode将在运行时填充,所以我无法像这样使用{{1}}。似乎使用多方法是一个很好的解决方案,不是吗?如果是这样,设计会是什么样的?

2 个答案:

答案 0 :(得分:1)

Multimethods(AKA multi dispatch)处理根据所涉及参数的运行时类型调度对单个函数的调用的问题。这似乎不是你的问题(或者我误解了你?),因为你有两个不同的方法名,在两种不同的类型上实现。

您的目标似乎是根据已注入类的运行时类型选择方法实现。目前尚不清楚您是否能够指示注射所采用的形式,但如果您是,那么为什么不直接注入实施?然后你可以使用隐式接口而不是显式接口。换句话说,为什么不注入类似functor的对象?

class TestBase
{
public:
    typedef std::function<void ()> Ticker;

    TestBase(Ticker hbTicker) : ticker{hbTicker} {}

    void HeartbeatTick() {
       ticker();
    }

    void setTicker(Ticker hbTicker){
        ticker = hbTicker;
    }

private:
    Ticker ticker;
};

如果满足您的要求,对我来说似乎不那么复杂。

如果确实需要实现多个调度,则可能需要在每个需要确定其运行时类型的参数上实现visitor模式。不确定这是否适用于多个参数(我至少没有尝试过多个参数)。或者您可以使用RTTI和案例陈述或类似的东西。

答案 1 :(得分:0)

我只是在这里傻了! 我只需要使用其他ChangeMode()方法,以便知道TestBaseTestOneModeBase类型:

template<typename Mode>
bool
IsSame( TestBase* base )
{
     return dynamic_cast<Mode*>(base) != nullptr;
};

template <class Mode>
void
ChangeMode()
{
    if( isSame<Mode>(this) )
    {
        // Change the ticker method
    }
    else
    {

    }
}