【问题标题】:Virtual base class initialization conundrum虚拟基类初始化难题
【发布时间】:2014-04-22 20:08:53
【问题描述】:

我在静态库中有以下构造(调度机制的一部分,为简洁起见删除了不相关的细节):

class Base {
protected:
    Base(Connection* conn = nullptr) : myConn(conn) {;} // = nullptr fixes the problem

    Connection* myConn;
};

class Handler : virtual public Base {
public:
    virtual void handleMessage(InputStream&) = 0;

protected:
    Handler(int id) : myId(id) {;} <<<<< Error <<<<<<<

    const int myId;
};

template<class EventType>
class TypedHandler : public Handler
{
protected:
    TypedHandler() : Handler(EventType::ID) {;}

    virtual void onEvent(const EventType&) = 0;

private:
    virtual void handleMessage(InputStream& message)
    {
        EventType event(message);
        onEvent( event );
    }
};

我完全知道最派生的类应该初始化基类,它看起来像:

class A : public TypedHandler<SuperEvent>
        , public TypedHandler<DuperEvent>
{
public:
    A(Connection* conn) : Base(conn) {}

    void onEvent(const SuperEvent&)
    { ... }

    void onEvent(const DuperEvent&)
    { ... }
};

但是我在标记的位置(VS 2012,MSVC++ 11)得到“错误 C2512:没有适当的默认构造函数可用的虚拟基类”,即使 Handler 从来都不是最衍生的......

想法?

编辑:通过允许生成默认构造函数(通过构造函数中的Connection* conn = nullptr),它可以工作。根据 Igor 的链接,不会在 Handler 构造函数中调用默认构造函数,因为 Handler 是虚拟的。

Edit2:通过将虚拟基类的默认构造函数设置为private,并将直接的两个子类设置为friends+非默认构造函数为protected,不仅可以编译,而且如果最派生类没有初始化正确的虚拟基类。所有复选框都打勾! :)

【问题讨论】:

  • 根据DR 257,感觉它应该可以工作(Handler 是抽象的),但事实并非如此。对于它的价值,GCC 也拒绝此代码。 GCC 错误here.
  • 谢谢@Igor,真令人失望。但是 GCC 的 bug 真的很老了,这方面没有任何进展吗?

标签: c++ visual-c++ virtual


【解决方案1】:

此问题已在 clang 3.4 中修复,但更早版本未修复。鉴于它是 编译器错误或至少是有争议的编译器特征,并且 Base(Connection&amp; conn) 受保护,您也许可以使用 一个面对面的条件编译解决方法,例如

class Base {
protected:
#if HAVE_BUG_GCC19249
    Base(Connection& conn = _workaround_bug_gcc19249_) : myConn(conn) {;}
#else
    Base(Connection& conn) : myConn(conn) {;}
#endif

    Connection& myConn;

#if HAVE_BUG_GCC19249
    static Connection _workaround_bug_gcc19249_;
    // ... conditional definition in implementation file.
#endif
};

【讨论】:

  • 是的,或者像我在编辑的帖子中所做的那样,选择默认为 nullptr 的 Connection*。
猜你喜欢
  • 2019-02-06
  • 2014-10-13
  • 2014-11-23
  • 2011-06-18
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 2012-08-31
相关资源
最近更新 更多