假设我有一个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 already mentioned)。
另一个很大的区别是,使用variant
,在访问期间根本不会发生任何动态多态(不需要RTTI)。
与std::visit
一起,有许多技巧可以确保在为给定的std::variant
调用适当的函数时(基本上)零运行时开销。虽然可能有非平凡的额外编译时间和内存使用量,因为它通过创建一个大的函数指针矩阵来实现这一点(关于它的See this excellent blog post from Michael Park)