【发布时间】:2016-11-04 21:18:32
【问题描述】:
我发现 clang 3.8.0 和 gcc 6.2.1 处理我认为是有效代码的方式存在一些差异。这是一个示例,clang++ --std=c++11 vitest.cpp 编译时没有注释:
#include <iostream>
class Processor {
public:
Processor( int i, float f ) {}
virtual ~Processor() noexcept {}
virtual void getStatistics() = 0;
};
class PageProvider : virtual public Processor {
public:
PageProvider( int i, float f )
// : Processor{i,f} // Without this, GCC wants to call default ctor
{}
virtual ~PageProvider() {}
};
class QuotePageProvider : public PageProvider {
public:
QuotePageProvider( int i, float f )
: Processor{i,f},
PageProvider{i,f}
{}
virtual void getStatistics() { std::cout << "Hi there" << std::endl; };
};
int main( int argc, char* argv[] )
{
PageProvider* prov2{new QuotePageProvider{1,2.2}};
prov2->getStatistics();
delete prov2;
}
第一个异常是 g++(使用相同的命令行参数)抱怨 PageProvider 构造函数:
vitest.cpp:16:2: error: no matching function for call to ‘Processor::Processor()’
这可以通过取消注释处理器的显式初始化来解决,如上所示。根据下面的aschepler's answer,这是一个已知的 gcc 错误。
抛开这些,事情变得更有趣了:
vitest.cpp: In constructor ‘QuotePageProvider::QuotePageProvider(int, float)’:
vitest.cpp:25:20: error: cannot allocate an object of abstract type ‘PageProvider’
PageProvider{i,f}
^
vitest.cpp:12:7: note: because the following virtual functions are pure within ‘PageProvider’:
class PageProvider : virtual public Processor {
^~~~~~~~~~~~
vitest.cpp:9:15: note: virtual void Processor::getStatistics()
virtual void getStatistics() = 0;
^~~~~~~~~~~~~
gcc 似乎坚持在PageProvider 中提供getStatistics() 的实现,以便编译QuotePageProvider,而clang 没有。我在编译with gcc 5.1 时得到了相同的结果。
我可以说服 gcc 通过执行以下任何操作来编译代码:
- 将
PageProvider的构造函数的参数数量减少到1 (与类型无关)。 - 使
PageProvider对Processor的继承成为非虚拟的。 - 在
QuotePageProvider的构造函数的初始化列表中,将PageProvider的初始化更改为使用括号而不是花括号。对上面Processor的初始化进行类似的更改没有效果。
这可能是标准中的一些奇怪的极端情况,两个编译器的解释不同,还是其中一个被破坏了?
【问题讨论】:
-
后半部分是另一个 GCC 错误。 (嗯,这是标准 IIRC 中的一个错误,它被严格执行,然后标准得到修复,然后 GCC 得到修复,但不完全。)
-
@T.C.宾果游戏,看起来就是这样。如果您想将您的 cmets 升级为答案,我会接受。