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

时间:2015-04-02 20:54:39

标签: c++ c++11 gcc c++14 c++03

以下代码在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) {}

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

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


我在网络上发现的only rel ated references人们在成员名称被意外地宏观扫描时遇到了错误,实际上导致了与上面相同的代码:

#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
};

那些人从未弄清楚错误的含义,尽管他们后来至少发现了为什么他们的程序被打破了。

3 个答案:

答案 0 :(得分:54)

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

  

构造函数可以这样写:

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

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

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

归功于http://www.softwarepreservation.org/projects/c_plus_plus/归档文件。

...哇,我刚刚意识到&#34; CFront&#34;是一个文字游戏。

答案 1 :(得分:23)

事实上,这不是有效的标准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&amp; T贝尔实验室1989; pdf

答案 2 :(得分:6)

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

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