在java中,要创建一个返回与参数类型相同的对象并扩展某个类的函数,我会键入:
public <T extends MyClass> T foo(T bar) {...}
有与此等效的 C++ 吗?
换句话说,我如何创建一个函数,该函数采用扩展某个类的任何类并返回相同的类型? (这是为了抽象/纯虚拟类的目的)。
原文由 ricky3350 发布,翻译遵循 CC BY-SA 4.0 许可协议
从技术上讲,正如其他答案所示,有一些方法可以在编译时将其限制为某种类型的子类型。然而,大多数时候,你会做
template <typename T> T foo(T bar) {...}
无需指定界限。
在 Java 中,泛型需要边界,因为泛型类或方法是与它的任何使用分开编译的。泛型类或方法被编译一次,成为字节码中的单个版本,该版本能够处理调用者向其抛出的任何满足其声明边界的参数。
编译器必须对方法体中 T
类型的使用进行类型检查,例如方法调用、字段访问等,但不知道 T
是什么,因此您必须提供一个界限,因此编译器可以满足例如一个方法调用是有效的,因为它是在满足该界限的所有类型上定义的。例如,如果您在方法的主体中有表达式 bar.baz()
,则编译器只会让您编译如果类型 MyClass
(以及它的所有子类型)提供该方法 .baz()
;如果您没有提供任何界限,编译器会抱怨 Object
(隐式上限)没有方法 .baz()
。
C++ 模板是不同的。模板化的类或函数被“实例化”(再次编译)它用于每个不同的类型参数。因此,在为特定 T
编译函数体时,编译器知道 T
是什么,并且能够直接对该类型的使用进行类型检查。
因此,如果您在函数体中有表达式 bar.baz()
,那就没问题了。如果您将此函数与 T
是扩展 MyClass
的类型一起使用,那么它将编译得很好,因为这样的类型有一个 .baz()
如果您将此函数与没有 .baz()
的类型一起使用,那么它将无法在该用法下编译。如果您不小心将函数与不扩展 MyClass
但具有 .baz()
的类型的函数一起使用,其参数类型和返回类型与您使用它的方式匹配,它也会编译;但这不一定是坏事。 C++ 模板通常不与类型层次结构一起使用,而是与类型需要提供的要求一起使用。因此,例如,排序算法不会要求其容器和/或元素类型扩展某个类型,而是要求容器提供某些特征(例如随机访问下标运算符),并且元素类型提供某些特征(例如小于运算符)。
原文由 newacct 发布,翻译遵循 CC BY-SA 3.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答4.1k 阅读✓ 已解决
如果您有可用的 C++11 或更高版本,我们可以在这里使用
enable_if
例如:
现场演示