因为我主要从事 C# 工作。经过相当长一段时间后,我不得不从事 C++ 项目,并且想知道为什么 C++ 不依赖继承或接口来实现相关方法,例如
std::vector<>::begin(T, Allocator)
和 std::list<T, Allocator>::begin()
?在 C# 中,这通常用于具有类似行为的类,例如 ICollection<T>
和 List<T>
上的 ReadOnlyCollection<T>
接口。
C++ 实际上以多种方式支持接口
通过虚函数。这是经典风格nomial subtyping,对应于您引用的 C# 方法
C++ 确实支持经典意义上的接口,其中接口类似于带有抽象函数的类。在 C++ 中,这将是纯虚函数。这相当于其他语言提供的功能。然而,这会带来性能损失,因为与常规函数(而且也可以内联)相比,调用虚拟函数会降低性能。
除了性能损失之外,缺点是无法向现有类型添加接口。 (这适用于所有具有此功能的语言,而不仅仅是 C++)
std::vector
或 std::list
没有基于虚拟功能的接口。尽管如此,他们还是遵循管理和概念惯例。两者都有迭代器(虽然属于不同的类,但都是迭代器)并且具有共同的功能,例如 begin
end
insert
、push_back
等。甚至还有可以在所有容器上操作的std::begin
。
Go 语言中也使用了接口的结构子类型。它提供了更多的灵活性和可扩展性。例如,可以向现有类型添加接口,而无需更改现有类型。
使用 C++20 概念,现在还可以显式指定类型的要求(即它们必须支持哪些方法,或者更一般地说,对它们进行操作的哪些表达式必须有效)。这定义了接口(或在 C++ 中如何调用它们的概念)。但这不是由类型实现者决定的,而是由类型的用法决定的。