我有一些类似于下面的代码,其中一组具有类似共享行为的类(Tool1,Tool2),都继承自一个抽象类(ITool)。所有这些类都拥有自己的相应类(Tool1Attachment,Tool2Attachment),这些类也继承自一个抽象类(IT附件)。
class ITool {
private:
virtual ? DoGetAttachment() = 0;
// Other shared behaviours...
public:
? GetAttachment() {return DoGetAttachment();}
// Other shared behaviours...
};
class Tool1: public ITool {
std::optional<Tool1Attachment> opt_attachment;
? DoGetAttachment() override;
public:
[...]
};
class Tool2: public ITool {
std::optional<Tool2Attachment> opt_attachment;
? DoGetAttachment() override;
public:
[...]
};
// --------------------------------
class IAttachment {
[...]
};
class Tool1Attachment : public IAttachment {
[...]
};
class Tool2Attachment : public IAttachment {
[...]
};
字符串
工具类有一个可选的上下文是有意义的,在任何给定的时间它可能有也可能没有一个实际的示例。
如果我有一个IAttachment,并希望获得IAttachment,就会出现问题。
我最初使用的是指针,即IAttachment* GetAttachment();
,它工作得很好。然而,它似乎失去了optional提供的一些更明确的缺失值检查,使得将来更容易遇到nullptr问题。
我还尝试了不同的结构(std::reference_wrapper)与可选,但不断遇到无效的协变错误。
有没有一种方法可以允许返回一个可选的(或类似的)结构?返回类型应该是什么样的?或者带nullptr检查的指针最适合这里?
? GetAttachment() {return DoGetAttachment();}
型
2条答案
按热度按时间2eafrhcq1#
指针是显而易见的解决方案(如果可选项为空,则使用空指针)。如果使用继承,则需要指针(或引用)无论如何,为了使多态性工作,C++支持协变返回类型,所以
Owner1
可以返回一个Owned1*
。检查返回的指针是否为空是标准的做法。另一种方法是返回一个optional<IOwned*>
(因为协方差在这里不起作用),但我看不出这会给你带来什么,除了额外的复杂性。fxnxkyjh2#
答案实际上归结为你对
DoGetAttachment
函数的期望。它应该把成员的“可选性”* 转发给调用者,并负责检查值是否存在?或者如果存储的std::optional
有值,DoGetAttachment
函数应该返回一个引用,如果没有值,则抛出一个异常?假设你想把可选性“转发”给函数的调用者,你基本上有两个选择。
选项1:使用(原始)指针
使用指针,就像你已经根据你的问题所做的那样。这是最简单的解决方案和标准做法。
选项二:
std::optional
和std::reference_wrapper
一起使用std::optional
不是多态的,所以你不能将std::optional<Derived>
转换为std::optional<Base>
。你可以做的是返回一个std::optional<Base*>
或std::optional<std::reference_wrapper<Base>>
。恕我直言,我更喜欢std::reference_wrapper
,因为否则你会在两个级别上拥有“optionalness”属性:一次用于std::optional
,一次用于存储指针。所以你需要检查两次是否存在。选项2给你的代码带来了一些额外的复杂性,这取决于你是否值得这样做。
使用
std::optional
的理由是,std::optional
允许你使用std::optional
的一元运算符,比如value_or
、and_then
、transform
(其中一些是C++23特性);std::optional
s不执行任何动态内存分配 (如果你需要的话)。下面是一个实现,其中
DoGetAttachment
返回std::optional<std::reference_wrapper<IToolAttachment>>
。字符串
输出量:
型
Live Code Demo