错误:过时的旧式基类初始化器

以下代码在C ++ 98,C ++ 11和C ++ 14模式下尝试的所有版本的GCC上产生后续编译错误:

struct T { T(void* x) : (x) {} }; // main.cpp: In constructor 'T::T(void*)': // main.cpp:3:18: error: anachronistic old-style base class initializer [-fpermissive] // T(void* x) : (x) {} // ^ // main.cpp:3:16: error: unnamed initializer for 'T', which has no base classes // T(void* x) : (x) {} 

当然,这显然是破坏代码,因为我实际上并没有初始化任何东西。

但为什么它是一个基础级的初始化者,为什么它是“不合时代的”,而不是简单的错误呢? 曾经有效吗? 什么时候? 这是什么意思?


我在网上发现的唯一相关 引用是,当一个成员的名字被意外地macros观化时,人们碰到错误,实际上导致与上面相同的代码:

 #define bar // ^ some library could have done this struct T { T(int x) : bar(x) // effectively just `: (x)` {} int bar; // will cause its own error }; 

那些人从来没有发现这个错误是什么意思,尽pipe他们后来至less发现了他们的程序被破坏的原因。

在第一个C ++编译器CFence 1984-5版本的文档中find:

构造函数可以这样写:

  vec.vec(int lb, int hb) : (hb-lb+1) { if (hb-lb<0) hb * lb low = lb; high = hb; } 

构造:(hb-lb + 1)用于指定基类构造函数vector()所需的参数列表。

有意义的,如果你想一想。 为了支持多重inheritance,可能会添加基类的显式名称。

感谢http://www.softwarepreservation.org/projects/c_plus_plus/用于归档文档。;

哇,我刚才意识到“CFront”是一个用语言expression的话题。

事实上,这不是有效的标准C ++,所以我们必须查看语言历史的年代来find这个变得无效的点。

1989年,当Stroustrup在1985年进一步定义“C ++”以来,以其名称开始进一步定义时,Stroustrup宣称基础初始化已经从语言的以前的化身中改变,以便应对多重inheritance:[1]

C ++编程语言[Stroustrup 1986]描述了C ++的定义和实现于1985年8月。 本文描述了从那时起语言的发展,并澄清了定义中的几点。 强调这些语言修改是扩展; C ++已经并将继续成为适合长期软件开发的稳定语言。 C ++的主要新特性是:多重inheritance ,types安全链接,更好的重载函数parsing,赋值和初始化的recursion定义,更好的用户定义内存pipe理function,抽象类,静态成员函数,const成员函数,受保护成员,操作符重载->和指向成员的指针。 这些function在C ++的2.0版本中提供。

[p214] 用于初始化基类和成员的语法已经扩展,以应对多重inheritance,并且更精确地定义了初始化的顺序。 [..]

文本接着展示了我们目前熟悉的基类初始化语法,正如Sneftel已经指出的那样(节省了我通过更多的旧文档来狩猎的麻烦!),但是这种情况到现在为止还不是那么晚在原来的C ++实现中,它本身是从“C with Classes”演化而来的。 因此,我们可以得出结论,C ++ 2.0在1989年引入了更为熟悉的语法,而这个“不合时宜”的版本在此之前是有效的。

注意,当然,在问题的代码中,没有基础。 所以,即使在C ++ 1.0中,程序最终也没有成功编译。 不过,我们已经发现为什么这样的语法正在被parsing。

GCC正在诊断一个模糊的,长期被遗忘的语法,这在C ++的化身中已经有三十年的历史了。


[1]“The Evolution of C ++:1985 to 1989”,Bjarne Stroustrup,AT&T贝尔实验室1989; PDF格式

这在ARM的第18.3.2节中具体描述为不合时宜。

这些function的原因通常是为旧版本的C ++或带有类的C提供连续性。 所有的“时代错误”都有不良的特征。 编译器不需要提供这样的function,但是,如果他们这样做的话,则有义务允许程序员停用它和/或被警告使用它。