虚基类初始化难题

时间:2014-04-22 20:08:53

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

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

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&)
    { ... }
};

但我得到&#34;错误C2512:没有合适的默认构造函数可用虚拟基类&#34;在标记的位置(VS 2012,MSVC ++ 11),即使Handler从来没有被认为是最多的...

想法?

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

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

1 个答案:

答案 0 :(得分:1)

此问题已在clang 3.4中修复,但不是更早。鉴于它是 编译器错误或至少是一个有争议的编译器特征,以及 Base(Connection& 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
};