错误:不合时宜的旧式基类初始化程序

Lig*_*ica 49 c++ gcc c++11 c++03 c++14

以下代码在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) {}
Run Code Online (Sandbox Code Playgroud)

当然,它显然是破碎的代码,因为我实际上并没有初始化任何东西.

但为什么它是基类初始化器,为什么它是"不合时宜的",而不是简单的错误?曾经有效吗?什么时候?这是什么意思?


我在网上找到的唯一的相关参考文献是,当一个成员名称被意外地宏出时,人们遇到了错误,实际上产生了与上面相同的代码:

#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
};
Run Code Online (Sandbox Code Playgroud)

那些人从来没有找到错误的含义,尽管他们后来至少发现了为什么他们的程序被打破了.

Sne*_*tel 57

在第一个C++编译器的CCront 1984-5版本的文档中找到:

构造函数可以这样写:

  vec.vec(int lb, int hb) : (hb-lb+1)
  {
      if (hb-lb<0) hb = lb;
      low = lb;
      high = hb; 
  }
Run Code Online (Sandbox Code Playgroud)

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

如果你考虑的话,这是有道理的.据推测,添加了基类的显式命名以支持多重继承.

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

......哇,我刚刚意识到"面对面"是一个文字游戏.

  • 我也是哇 (6认同)

Lig*_*ica 24

实际上,这不是有效的标准C++,因此我们必须查看语言历史的历史,以找到它变得无效的点.

1989年,当自1985年以该名称开始进一步定义"C++"时,Stroustrup宣称基础初始化已经从语言的先前化身改变,以应对多重继承:[1]

[p191] C++编程语言[Stroustrup 1986]描述了1985年8月定义和实现的C++.本文描述了从那时起语言的发展,并澄清了定义中的几点.强调这些语言修改是扩展; C++已经并将继续是一种适合长期软件开发的稳定语言.C++的主要新特性是:多重继承,类型安全链接,更好的重载函数解析,赋值和初始化的递归定义,更好的用户定义内存管理工具,抽象类,静态成员函数,const成员函数,受保护成员,运算符重载->和成员指针.这些功能在C++的2.0版本中提供.

[p214] 初始化基类和成员的语法已经扩展到可以处理多重继承,并且已经更精确地定义了初始化的顺序.[..]

本文接着演示了我们目前熟悉的基类初始化语法,正如Sneftel已经指出的那样(省去了通过任何更旧的文档进行搜索的麻烦!),这种情况并非如此. 1985年,在原始的C++实现中,它本身是从"C with Classes"演变而来的.因此,我们可以得出结论,C++ 2.0在1989年引入了更为熟悉的语法,这个"不合时宜"的版本在此之前是有效的.

当然,请注意,在问题的代码中,没有基础.因此,即使在C++ 1.0中,该程序最终也不会成功编译.但是,我们已经发现了为什么以这种方式解析语法.

值得注意的是,GCC正在诊断模糊不清,长期被遗忘的语法,这种语法在C++的任何版本中都有效近三十年.


[1]"C++的演变:1985年至1989年",Bjarne Stroustrup,AT&T贝尔实验室1989; PDF格式


Pet*_*ter 6

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

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