在C++有没有办法让孩子重用祖父中定义的纯虚函数的 Parent 类实现
In C++ Is there a way for the Child to reuse the the Parent class implementation of the pure virtual function defined in GrandParent
考虑下面的代码,EventGeneratorBase 是一个帮助程序类,旨在为AddEventHandler()
提供实际的实现,我想在类RemoteControl
中使用该实现,而不是显式定义它。我知道如果不定义方法就不可能实例化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;
}
您的问题是您的RemoteControl
对象中有两个不同的 IEventGenerator<IControlEvents>
类型的子对象。 一个通过EventGeneratorBase<IControlEvents>
,一个通过IRemoteControl
。
有两种方法可以防止您有两个不同的子对象。 首先是继承virtual
ly,从两个地方的IEventGenerator<TEventHandler>
。 这具有适度的运行时成本。 只需在每次从IEventGenerator<?>
继承之前添加virtual
,您就完成了。
第二种方法是注意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;
};
现在,转到此处:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
并改变我们的继承方式。 我们现在在我们和IRemoteControl
之间插入EventGeneratorHelper
,所以它们现在共享相同的共同IEventGenerator
。
这消除了对virtual
继承的需要,但会增加编译时间,并可能导致一些可执行代码膨胀。
我们可以更进一步。 将此添加到EventGeneratorHelper
:
template<class Action>
void FireEvents( Action&& action ) const {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
action(t);
}
}
}
这将RemoteControl
减少到:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
void Toggle() {
this->FireEvents([](std::shared_ptr<IRemoteControl> const& ptr){
t->PowerOn();
t->PowerOff();
});
}
};
我认为这很好 - 要求客户知道正确的迭代方式似乎很愚蠢。
继承层次结构中有问题。
template <class TEvents> struct EventGeneratorBase :IEventGenerator<TEvents> {
[...]
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
[...]
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
[...]
};
这不是你所期望的。相反,您的类RemoteControl
从IEventGenerator
继承两次,一次从IRemoteControl
继承,一次从EventGeneratorBase
继承。
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数