我在静态库中有以下构造(调度程序机制的一部分,为简洁起见删除了不相关的详细信息):
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,不仅可以编译,而且如果最派生类没有初始化,则编译失败虚拟基类正确。勾选所有复选框! :)
答案 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
};