实现虚拟方法的组合行为
Implementing compositional behaviour for virtual methods
假设我有几个类的层次结构:
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();
...
}
我相信这种实现有一个严重的问题:人们总是必须记住在覆盖时调用 base 实现。
另类:
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;
};
我不确定我是否正确理解,但这似乎可以通过"使公共接口非虚拟,虚拟化私有功能"的建议很好地解决。
我认为这是在开闭原则中体现的。该技术如下:
#include <iostream>
class B {
public:
void f() {
before_f();
f_();
};
private:
void before_f() {
std::cout << "will always be before f";
}
virtual void f_() = 0;
};
class D : public B{
private:
void f_() override {
std::cout << "derived stuffn";
}
};
int main() {
D d;
d.f();
return 0;
}
您基本上剥夺了后代类覆盖公共接口的权限,仅自定义公开的部分。基类B
严格强制要求在派生中的实际实现之前调用所需的方法。作为奖励,您不必记住调用基类。
当然,您也可以f
虚拟的,D
决定。
相关文章:
- 虚拟决赛作为安全
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 可组合的lambda/std::函数与std::可选
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 如何在C++中获得"静态纯虚拟"功能?
- C++无法定义虚拟函数 OUTER 类和头文件
- 混合组合和继承的C++问题
- 我需要将多个函数组合为一个函数
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 通过组合不同的类型来创建唯一的id
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 模板元编程:如何将参数包组合成新的参数包
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 生成组合的虚拟按键以获得 â、ó、ć 等字符
- 实现虚拟方法的组合行为
- 如何扩展/组合包含纯虚拟函数的接口类
- 虚拟组合键