为什么clang和gcc不同意这个虚拟继承代码?

时间:2016-11-04 21:18:33

标签: c++ c++11 g++ clang++

我发现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 bug。

放弃了,事情变得更有趣:

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构造函数的init-list中,将PageProvider的初始化更改为使用括号而不是curlies。对上面Processor的初始化进行的类似更改无效。

这可能是标准中的一些奇怪的角落,两个编译器的解释方式不同,或者其中一个被破坏了?

1 个答案:

答案 0 :(得分:4)

这是gcc bug 53878

抽象类不需要构造其虚拟基类。