为什么 C++ 和 Java 中的构造函数调用需要显式类型参数

Why do constructor calls in C++ and Java require explicit type parameters?

本文关键字:函数调用 类型参数 C++ Java 为什么      更新时间:2023-10-16

C++和Java在处理参数多态性方面有这种相似之处:两者都会将类型参数推断为常规函数或方法,但要求程序员在调用构造函数时显式给出类型参数(尽管这在Java 7中发生了变化)。

这种行为背后的技术原因是什么?

编辑:我错误地认为这也适用于Scala。下面是一个来自 Java 的示例:

class Foo<T> {
    Foo(T x) { }
}
<T> void foo(T x) { }

Foo<Integer> f = new Foo(3);
foo(3);

两者都是合法的,但第一个创建"原始类型"而不是Foo<Integer>,并执行未经检查的赋值。

这是因为C++模板可以专业化。

这意味着仅仅因为有一个主要定义:

template<typename T>
class Foo
{
    Foo(T x) { }
};

而且显然int会被Foo<int>(int)接受,完全有可能还有一个专门的定义

template<>
class Foo<Foobar>
{
    Foo(int x) { }
};

它还接受int参数。

将用户定义的类型转换添加到组合中,您会发现无法从函数参数中找出类的类型参数。

事实上,允许推断构造函数的类型参数。 但不是类模板参数的推断。 例如,在构造智能指针时允许隐式上播:

template<typename T>
class a_smart_ptr
{
    template<typename TOther>
    a_smart_ptr(TOther* p) { }
};