我对C ++中的设计有疑问。
正如您在下面的代码中看到的那样,存在设计问题。我希望能够拥有一个TestClass
,它继承自ModeBase
(本例中为ModeOne
和ModeTwo
)的零个或多个类。如果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}}。似乎使用多方法是一个很好的解决方案,不是吗?如果是这样,设计会是什么样的?
答案 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()
方法,以便知道TestBase
,TestOne
是ModeBase
类型:
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
{
}
}