第 14 章. 使用 std::variant 和 std::visit
你已经了解如何通过类来实现行为的变体,方法是从一个提供接口的抽象基类开始。 然后,你可以根据需要添加任意数量的派生类,以提供不同的实现。 我用了几章的篇幅,向你介绍了在 C++ 中实现这一目标的所有基础构建块。 虽然需要几个组成部分,但这种方法具有可扩展性:你可以根据需要继续添加额外的派生类型,而无需修改现有代码。
你还可以使用 C++ 的另一项特性——std::variant——来实现行为的变体。
std::variant是 C++17 中引入的一个类模板。
std::variant包含多种备选类型中的一种,C 语言程序员可能会将其视为一种类似于联合体(union)的实现方式。
这些类型之间可能完全无关。
这种方法要求在设计之初就确定一组固定的类型,因此其可扩展性不如面向对象编程(OOP)。
不过,std::variant允许您以非侵入式的方式扩展该类型集的行为。
如果您想为类添加功能,可以在基类中添加一个新方法,这将影响所有派生类。
若使用std::variant,则可在不改变其包含的类型的情况下提供新功能。
面向对象编程(OOP)便于添加新类型,但难以添加新操作。
变体(Variants)则便于添加新操作,但难以添加新类型,因此 OOP 和变体各有取舍。
本章将向您展示如何使用std::variant在您的交易游戏中添加潜在的奖金或罚金:例如利息支付。
您还将了解到另外两个特性:std::optional和std::any,它们同样支持多种类型,但设计目标各不相同。
创建和使用 std::variant
让我们为您的交易游戏增添一些额外可能性。
您可以设置一条新闻标题,其类型可以是std::string,并创建其他类型来表示罚款、赠礼或利息支付。
您将编写一个新函数,该函数有时会随机返回其中一种类型。
游戏将报告事件是否发生,要么显示该std::string,要么显示一条消息并相应调整资金。
如何返回多种互不相关的类型之一?
如果你有一个基类,可以返回该类的智能指针,多态行为会自动处理相关事宜。
对于互不相关的类型,这种方法行不通。
不过,你可以将任何类型放入std::variant 中。
让我们先在新的events.h文件中定义一些用于罚款、礼物或利息支付的新类型。
由于你希望事件仅偶尔发生,因此也可以定义一个 nonevent。
然后,你可以在std::variant 中使用这些事件和 nonevent:
#include<iostream>#include<string>#include<variant>namespacestock_prices{structNothing{};structFixedFine{doublefine{};};structGift{doublegift{};};structInterestPayment{doublepercent{};
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access