[英]In C++ Is there a way for the Child to reuse the the Parent class implementation of the pure virtual function defined in GrandParent
Consider the below code, EventGeneratorBase is a helper class intended to provide the actual implementation for AddEventHandler()
and I would like to use that implementation in the class RemoteControl
instead of explicity defining it. 考虑下面的代码,EventGeneratorBase是一个帮助程序类,旨在提供AddEventHandler()
的实际实现,我想在RemoteControl
类中使用该实现,而不是显式定义它。 I know it's not possible to instantiate RemoteControl
without defining the method but is there a shortcut or an easy way to avoid manually defining the methods. 我知道在不定义方法的情况下无法实例化RemoteControl
,但是有没有捷径或简便的方法来避免手动定义方法。
Note: The code in it's present form doesn't compile because RemoteControl can't be instantiated. 注意:由于无法实例化RemoteControl,因此当前形式的代码无法编译。
#include <iostream>
#include <vector>
#include <memory>
template<class TEventHandler> struct IEventGenerator {
virtual ~IEventGenerator() = default;
virtual void AddEventHandler(std::weak_ptr<TEventHandler> eventHandler) = 0;
};
template <class TEvents> struct EventGeneratorBase : IEventGenerator<TEvents> {
void AddEventHandler(std::weak_ptr<TEvents> target) {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
struct IControlEvents {
virtual ~IControlEvents() = default;
virtual void PowerOn() = 0;
virtual void PowerOff() = 0;
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
virtual ~IRemoteControl() = default;
virtual void Toggle() = 0;
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
// I don't want to define AddEventHandler() in this class and
// would like to inherit the implementation from EventGeneratorBase
void Toggle() {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
t->PowerOn();
t->PowerOff();
}
}
}
};
struct Light : IControlEvents {
Light(std::string color) : _color(color) { }
void PowerOn() {
std::cout << _color << "::Light ON!" << std::endl;
}
void PowerOff() {
std::cout << _color << "::Light OFF!" << std::endl;
}
private:
std::string _color;
};
int main() {
std::shared_ptr<IRemoteControl> remote(new RemoteControl); // ERROR: Can't instantiate
std::shared_ptr<IControlEvents> light1(new Light("GREEN"));
std::shared_ptr<IControlEvents> light2(new Light("RED"));
remote->AddEventHandler(light1);
remote->AddEventHandler(light2);
remote->Toggle();
return 0;
}
Your problem is that you have two distinct sub-objects of type IEventGenerator<IControlEvents>
within your RemoteControl
object. 您的问题是,在RemoteControl
对象中有两个类型为IEventGenerator<IControlEvents>
不同子对象。 One via EventGeneratorBase<IControlEvents>
and one via IRemoteControl
. 一个通过EventGeneratorBase<IControlEvents>
,另一个通过IRemoteControl
。
There are two ways to prevent you from having two distinct subobjects. 有两种方法可以防止您拥有两个不同的子对象。 The first is to inherit virtual
ly from IEventGenerator<TEventHandler>
in both spots. 首先是在两个地方都从IEventGenerator<TEventHandler>
继承virtual
ly。 This has a modest run-time cost. 这具有适度的运行时成本。 Simply add virtual
before every case of inheritance from IEventGenerator<?>
and you are done. 只需在从IEventGenerator<?>
继承的每种情况下添加virtual
,即可完成。
A second method is to note that EventGeneratorBase
is intended to help with implementing IEventGenerator
. 第二种方法是注意EventGeneratorBase
旨在帮助实现IEventGenerator
。
template<class T> struct tag{using type=T;};
template<class Tag> using type_t=typename Tag::type;
template<class TEventHandler>
tag<TEventHandler> get_event_handler_type(
IEventGenerator<TEventHandler> const*
) { return {}; }
template<class X>
using event_handler_type = type_t< decltype( get_event_handler_type( (X*)nullptr ) ) >;
template <class Base, class TEvents = event_handler_type<Base>>
struct EventGeneratorHelper :
Base
{
void AddEventHandler(std::weak_ptr<TEvents> target) override {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
now, go down to here: 现在,转到此处:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
and change how we inherit. 并改变我们的继承方式。 We now interpose EventGeneratorHelper
between us and IRemoteControl
, so they now share the same common IEventGenerator
. 现在,我们在IRemoteControl
和EventGeneratorHelper
之间插入EventGeneratorHelper
,因此它们现在共享相同的公用IEventGenerator
。
This removes the need for virtual
inheritance, but does up your compile time, and can cause some executable code bloat. 这样就消除了对virtual
继承的需求,但是却增加了编译时间,并可能导致某些可执行代码膨胀。
We can go a step further. 我们可以更进一步。 Add this to EventGeneratorHelper
: 将此添加到EventGeneratorHelper
:
template<class Action>
void FireEvents( Action&& action ) const {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
action(t);
}
}
}
which reduces RemoteControl
to: 将RemoteControl
减少为:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
void Toggle() {
this->FireEvents([](std::shared_ptr<IRemoteControl> const& ptr){
t->PowerOn();
t->PowerOff();
});
}
};
which I think is nice -- requiring clients to know the right way of iterating seems silly. 我认为这很好–要求客户知道正确的迭代方式似乎很愚蠢。
You have a problem in your inheritance hierarchy. 您的继承层次结构中有问题。
template <class TEvents> struct EventGeneratorBase :IEventGenerator<TEvents> {
[...]
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
[...]
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
[...]
};
This is not doing what you might expect. 这没有达到您的期望。 Instead, your class RemoteControl
inherits twice from IEventGenerator
, once from IRemoteControl
and once from EventGeneratorBase
. 而是,类RemoteControl
从IEventGenerator
继承两次 ,一次从IRemoteControl
继承,一次从IRemoteControl
EventGeneratorBase
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.