【发布时间】:2020-07-08 23:58:45
【问题描述】:
我无法找到关于我认为应该是相当常见的问题模式的最佳实践信息。
我将从一个特定的(与软件更新相关的)示例开始,因为它使讨论更加具体,但问题应该是相当笼统的。
假设我有一个软件更新界面:
struct Software_updater {
virtual ~Software_updater() = default;
virtual void action1(const Input1& input1) = 0;
virtual void action2() = 0;
virtual bool action3(const Input2& input2) = 0;
virtual Data1 info1() = 0;
virtual Data2 info2() = 0;
// etc.
};
对于我的第一个实现A,我很幸运,一切都很简单。
class A_software_updater : public Software_updater {
// ...
};
然而,B_software_updater 更复杂。就像在A-case 中一样,它以非平凡的方式连接到目标以进行更新并保持目标连接状态。但更重要的是,它可以更新两个镜像:应用程序镜像和引导加载程序镜像。
就像我目前所拥有的一样,我认为没有真正的理由进行重构,所以我认为我可以在此基础上进行构建。我想出了以下解决方案:
class B_software_updater {
public:
Software_updater& application_updater() { return application_updater_; }
Software_updater& boot_loader_updater() { return boot_loader_updater_; }
private:
class Application_updater : public Software_updater {
// ...
} application_updater_;
class Boot_loader_updater : public Software_updater {
// ...
} boot_loader_updater_;
};
即我返回非const 对“接口”成员变量的引用。请注意,它们不能是const,因为它们处于静音状态。
请求 1:我认为上面的解决方案是一个干净的解决方案,但我很乐意得到一些确认。
事实上,我最近遇到了一个问题,即必须根据编译时特性的选择,在类中选择性地提供接口,我相信上面的模式也可以解决这个问题:
struct Optional_interface {
virtual ~Optional_interface() = default;
virtual void action1(const Input1& input1) = 0;
virtual void action2() = 0;
virtual bool action3(const Input2& input2) = 0;
virtual Data1 info1() = 0;
virtual Data2 info2() = 0;
// etc.
};
class A_implementation {
public:
#ifdef OPTIONAL_FEATURE
Optional_interface& optional_interface() { return optional_implementation_; }
#endif
// ...
private:
#ifdef OPTIONAL_FEATURE
class Optional_implementation : public Optional_interface {
// ...
} optional_implementation_;
#endif
// ...
};
请求 2:我在 A_implementation- 处找不到 simple(如:不是不必要的复杂的基于模板)和简洁的方式来表达编译时可选继承等级。可以吗?
【问题讨论】:
-
为什么不将
optional_implementation_;设为指向适当接口的唯一指针,并仅在编译时选项打开时填充它?让optional_interface()返回指针而不是引用,让用户知道他们可能一无所获。一般来说,摆弄接口是个坏主意——它会弄乱 ABI 和通用接口的整个概念。最好只为界面提供选项以返回“无数据”或“不支持此功能”。 -
@ALX23z,好点,但我猜每个硬币都有两个面。当您考虑一致的 ABI 时,作为一名嵌入式开发人员,我正在考虑不要链接不必要的东西。假设 ABI 一致性不是我的应用程序的要求。我的问题实际上是关于将非常量引用(或就此而言的指针,从那个角度来看没有什么不同)返回到“接口”成员变量。由于您在这方面似乎没有问题,因此我会将您的评论视为积极意见。
-
返回对成员变量的引用并长期使用它们的唯一问题是它们在移动时无效 - 这导致代码对于开发来说很笨重 - 但在您的情况下这可能不是问题.
-
@ALX23z,无论是否适用于我的情况,这仍然是一个非常可怕的问题。你逼我多想,谢谢。我想我刚刚为我的问题找到了更好的解决方案。我可能会将其发布为答案。
标签: c++ inheritance design-patterns interface