>假设我有一个Shape
基类和Circle
、Line
和Point
派生类。我有两个功能。
std::variant<Circle, Line, Point> process(const Shape &s);
Shape process(const Shape& s);
我可以传入我的任何派生类并在第二个函数中返回一个 Shape 对象,变量只是一个联合,可以在任何给定时间容纳我的任何派生类变量。
现在有了std::variant
,我还可以使用一个visitor
,在那里我可以根据我的变体当前持有的类型来处理一些函数(我可以创建一个函数对象并将其传递给std::transform
并将其应用于我的每个对象(。但是,我可以将该函数virtual
在我的基类中,并让每个派生类实现它。
那么,variant
只是一种方便吗?
那么,变体只是一种方便吗?
不,它们是不同的概念。主要区别在于,一方面std::variant
可以使用不相关的类型,包括像int
这样的内置类型,这在虚拟函数中是不可能直接实现的。另一方面,std::variant
必须知道它在编译时正在使用的类型。例如,可以通过仅链接其他对象模块来添加具有虚拟函数的类型,而无需重新编译其余代码或将共享库动态加载到现有应用程序(您甚至不必重新启动应用程序(,而使用std::variant
您必须重新编译处理std::variant
包含类型的代码。
但是,我可以在我的基类中使该函数成为虚拟函数,并让每个派生类实现它。
是的。。。。如果variant
中的所有元素共享一个共同的基础(Slava 已经提到过(。
另一个很大的区别是,对于variant
,在访问期间不一定会发生任何动态多态性(不需要RTTI(。
结合std::visit
,有很多技巧可以确保在为给定std::variant
调用适当的函数时(基本上(零运行时开销。尽管可能会有不平凡的额外编译时间和内存使用,因为它通过创建函数指针的大矩阵来实现这一点(请参阅Michael Park的这篇出色的博客文章(