C++是否被认为是弱类型语言?为什么?

28

我一直认为C ++是最强类型的语言之一。
因此,当看到本文第3表格指出C ++是弱类型时,我感到非常震惊。

显然,

由于类型转换,C和C ++被认为是弱类型,因为可以将结构体字段解释为整数指针。

是否只存在类型转换?这些显式转换的明确性是否不重要?

更普遍地说,C ++真的被普遍认为是弱类型吗?为什么?


6
C ++并不是弱类型语言,但是如果你想的话,可以破坏类型系统。因此,有人可以认为它不是完全强类型语言。 - juanchopanza
5
我认为“弱类型”是一个相当主观的术语。“严格类型”和“静态类型”与“松散类型”和“动态类型”的区分更为客观,更为精确。从我所了解的情况来看,一般人将“弱类型”作为贬低性词汇使用,意思是“我不喜欢这种语言中的类型概念”。对于那些无法提出专业技术论据反对某种特定语言的人来说,这有点像是攻击别人的语言(或者更确切地说是针对语言的争论)。 - The Paramagnetic Croissant
1
@Mehrdad 它也有稍微不同的解释; 通常被接受的意思是“如果类型不匹配,编译器会生成错误”。另一种解释是“没有或很少隐式转换”。基于此,C++实际上可以被认为是一种严格类型的语言,并且大多数情况下它确实被认为是这样。 - The Paramagnetic Croissant
4
Bjarne Stroustrup 的书在第 2 页提到 C++ 是一种强类型语言。比他更了解这个问题的人还有谁呢 :-) - Damon
@MatsPetersson:我认为值得指出的是,警告也可以被升级为错误(例如使用g++时的-Werror)。 - PaulR
显示剩余8条评论
6个回答

39

这篇论文首先声明:

相反,如果类型混淆可以悄无声息(未被检测到)地发生,并最终导致难以定位的错误,则语言是弱类型的。

然后它声明:

C和C++也被认为是弱类型的,因为由于类型转换,可以将结构的字段解释为整数而不是指针。

对我来说,这似乎是一种矛盾。在C和C++中,由于有类型转换,因此可能会发生的类型混淆不会悄无声息发生!这并没有证明这两种语言是弱类型的,至少根据那篇论文的定义。

也就是说,根据该论文的定义,C和C++仍然可能被认为是弱类型的。正如已经在问题评论中指出的那样,语言支持隐式类型转换的情况很多。许多类型可以隐式转换为bool,类型为int的字面零可以悄无声息地转换为任何指针类型,存在不同大小的整数之间的转换等。因此,这似乎是将C和C++视为弱类型的一个很好的理由。

对于C语言(而非C++),还存在一些更危险的隐式转换,值得一提的是:
int main() {
  int i = 0;
  void *v = &i;
  char *c = v;
  return *c;
}

就本文而言,这必须被视为弱类型。位的重新解释是默默发生的,并且通过修改它以使用完全不相关的类型,可以使其变得更糟,这具有静默未定义行为,通常具有重新解释位的相同效果,但在启用优化时会以神秘但有时令人愉快的方式爆炸。

总的来说,我认为“强类型”和“弱类型”没有固定的定义。有各种等级,与汇编相比较强类型的语言可能与Pascal相比较弱类型。要确定C或C ++是否为弱类型,首先必须问您想让弱类型意味着什么。


2
@Mehrdad 同意,并且我扩展了我的回答。 - user743382
4
不行,它们不能。 "Cast" 的意思是"显式转换"(或者更具体地说,用于编写显式转换的语法)。就像我在答案中已经提到的那样,存在隐式转换,但它们不被称为casts。 - user743382
1
@AndreyChernyakhovskiy:在C++中不会隐式发生不安全转换,但在C中会(例如指针转换)。 - user541686
1
@Mehrdad Ah,是的,我认为你可能有一个很好的观点。我应该把它加到我的答案中。 - user743382
1
我认为这里没有被提及的一个区别(尽管这里有许多经验丰富并且意识到这一点的人),除了 C 和 C++ 的技术差异(合法转换)之外,在惯用代码的类型强度上存在着很大的差异。例如,C 中的省略号参数是合法的 C++ 语法,但不是惯用的写法(已被强类型化的可变参数模板替换)。另一个例子:在 C 中,用户状态回调是通过接受 void* 类型的函数指针来处理的,而在 C++ 中则通过函数对象 / std::function 来处理。通常情况下,在 C++ 中使用 void* 的情况要少得多。等等。 - Nir Friedman
显示剩余12条评论

13
“弱类型”是一个相当主观的术语。我更喜欢“严格类型”和“静态类型”相对于“松散类型”和“动态类型”,因为它们是更客观和更精确的词。
据我所知,人们通常使用“弱类型”作为一种贬低性陈述来表达“我不喜欢这种语言中的类型概念”。对于那些无法提出专业或技术论据反驳特定语言的人来说,这有点类似于“以人身攻击为论证”。
术语“严格类型”也有稍微不同的解释;在我的经验中,普遍接受的意义是“如果类型不匹配,则编译器会生成错误”。另一种解释是“没有或很少隐式转换”。基于此,C++实际上可以被认为是一种严格类型的语言,而且大多数情况下也被认为是如此。我想说,关于C++的普遍共识是它是一种严格类型的语言。
当然,我们可以尝试更加细致入微地探讨这个问题并说语言的某些部分是严格类型的(这是大多数情况),其他部分是松散类型的(例如算术转换和四种显式转换中的一些隐式转换)。
此外,有一些程序员,特别是初学者,他们不熟悉超过几种语言,不打算或不能区分“严格”和“静态”,“松散”和“动态”,并根据他们有限的经验(通常是流行脚本语言中的动态性和松散类型的相关性)混淆这两个 - 否则正交 - 概念。
实际上,C++的一些部分(虚拟调用)强制要求类型系统部分动态,但标准中的其他事物要求它是严格的。再次强调,这不是问题,因为这些是正交概念。

总之,也许没有一种语言完全、完美地适合某个类别,但是我们可以说出给定语言的哪个特定属性占主导地位。 在C++中,严格性绝对占主导地位。


4
既然C++的创建者Bjarne Stroustrup在《C++程序设计语言》(第四版)中说这门语言是强类型的,那我就相信他的话:
“C++编程基于强静态类型检查,并且大多数技术旨在实现高级抽象和程序员想法的直接表示。通常可以在不牺牲运行时和空间效率的前提下完成此操作,相较于低级别技术而言。为了获得C++的好处,从其他语言转入C++的程序员必须学习和内化习惯用法的C++编程风格和技巧。同样适用于习惯于早期和表达能力较差版本的C++的程序员。”
1994年的视频讲座中,他还表示C语言的弱类型系统真的很困扰他,这也是他让C++成为强类型的原因。《C++的设计》——Bjarne Stroustrup讲座

3

与此相反,如果类型混淆可以默默发生(无法检测),并最终导致难以定位的错误,则语言是弱类型的。

例如,在C++中就可能会出现这种情况:

#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <limits>

void f(char n) { std::cout << "f(char)\n"; }
void f(int n) { std::cout << "f(int)\n"; }
void g(int n) { std::cout << "f(int)\n"; }

int main()
{
    float fl = M_PI;   // silent conversion to float may lose precision

    f(8 + '0'); // potentially unintended treatment as int

    unsigned n = std::numeric_limits<unsigned>::max();
    g(n);  // potentially unintended treatment as int
}

此外,由于类型转换,C和C++被认为是弱类型语言,因为可以将结构体中的整数字段解释为指针。但通过任何隐式转换都不可能实现这一点,因此这是一个愚蠢的论点。C++允许在类型之间进行显式转换,但这并不算“弱”-这不会像本站上的定义那样意外/无声地发生。
“存在类型转换就足够了吗?这些转换的明确性是否重要?”明确性是IMHO的一个关键考虑因素。让程序员覆盖编译器对类型的了解是C++的“强大”功能之一,而不是某种弱点。它不容易被意外使用。
更一般地说,“C++是否真的被普遍认为是弱类型语言?为什么?”不是-我认为它不被接受。C++具有相当强的类型,历史上导致麻烦的宽松方式已被修剪,例如从void *到其他指针类型的隐式转换以及更精细的控制与显式转换运算符和构造函数。

1

总体而言:

这个主题存在一些混淆。有些术语会因书籍而异(不考虑互联网),有些可能随着时间的推移而改变。

以下是我从书籍“编译器工程”(第二版)中理解的内容。


1. 无类型语言

完全没有类型的语言,例如汇编语言。


2. 弱类型语言:

具有较差的类型系统的语言。 此处的定义是故意模糊的。


3. 强类型语言:

每个表达式都具有明确的类型的语言。PL可以进一步分类为:

  • A. 静态类型: 在编译时为每个表达式分配类型。
  • B. 动态类型:某些表达式只能在运行时分配类型时。


C++是什么?

嗯,它肯定是强类型的。大多数情况下它是静态类型的。 但由于一些表达式只能在运行时分配类型,我想它属于3.B类别。

PS1:来自书籍的注释:

一个强类型的语言,可以进行静态检查,但由于某些原因可能只使用运行时检查实现。

PS2:最近发布了第三版

我没有拥有它,所以不知道在这方面是否有任何改变。 但总的来说,“语义分析”章节的标题和目录顺序都发生了变化。


-1

让我给你举个简单的例子:

 if ( a + b )

C/C++ 允许从 float 到 int 再到 Boolean 的隐式转换。

强类型语言不允许这种隐式转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接