c++ - 为虚拟方法实现组合行为
问题描述
假设我有几个类的层次结构:
class A {
public:
virtual void DoStuff() = 0;
};
class B : public A {
public:
// Does some work
void DoStuff() override;
};
class C : public B {
public:
// Calls B::DoStuff and does other work
void DoStuff() override;
};
它可以天真地实现:
void Derived::DoStuff() {
Base::DoStuff();
...
}
我相信这个实现有一个严重的问题:人们总是必须记住在覆盖时调用基本实现。
选择:
class A {
public:
void DoStuff() {
for (auto& func: callbacks_) {
func(this);
}
}
virtual ~A() = default;
protected:
template <class T>
void AddDoStuff(T&& func) {
callbacks_.emplace_back(std::forward<T>(func));
}
private:
template <class... Args>
using CallbackHolder = std::vector<std::function<void(Args...)>>;
CallbackHolder<A*> callbacks_;
};
用法:
class Derived : public Base {
public:
Derived() {
AddDoStuff([](A* this_ptr){
static_cast<Derived*>(this_ptr)->DoStuffImpl();
});
}
private:
void DoStuffImpl();
};
DoStuff()
但是,与第一个实现相比,我相信在实际调用时它会产生大量开销。在我看到的用例中,对象的长构造可能不是问题(如果他愿意,也可以尝试实现诸如“短向量优化”之类的东西)。
另外,我认为每种DoStuff
方法的 3 个定义有点过多的样板文件。
我知道通过使用类似于 CRTP 的继承模式可以非常有效地解决它,并且可以将基于模板的解决方案隐藏在接口类后面(A
在示例中),但我一直想知道——难道不应该有更简单的解决方案吗?
我call DERIVED implementation FROM BASE, if and only if derived class exists and it has an overriding method
对长继承链(或等效的东西)的良好实现感兴趣。
谢谢!
编辑:我知道@Jarod42 的回答中描述的一个想法,我认为它不合适,因为我认为它对于长继承链来说是丑陋的——必须为每个层次结构使用不同的方法名称。
解决方案
您可以将您的课程更改B
为:
class A {
public:
virtual ~A() = default;
virtual void DoStuff() = 0;
};
class B : public A {
public:
void DoStuff() final { /*..*/ DoExtraStuff(); }
virtual void DoExtraStuff() {}
};
class C : public B {
public:
void DoExtraStuff() override;
};
推荐阅读
- python - Python类型注解:继承方法的返回类型
- json - 从 JSON 反序列化 IndexingPolicy(Azure Cosmos DB)
- junit - 如何使用when...then模拟层次结构吸气剂
- javascript - 反应:动态添加值到下拉列表
- c# - AuthorizationHandler 和 Cookie 身份验证不能很好地结合在一起
- sql - 大于或等于 ALL() 且等于 MAX() 速度
- spring-boot - 以特定格式开头的apache骆驼文件过滤器
- python - Python Pandas 是否有办法指定一个列来计算每次出现的值组合?
- php - 如何从 Laravel 中的 select() 方法中替换值
- azure-blob-storage - azure Blob REST API 使用带有 SASkey 的 Curl 将数据从 RemoteServer 移动到存储帐户