模板错误:没有适当的默认构造函数可用

时间:2011-03-07 02:39:00

标签: c++ templates constructor

问题是,我不是(知道尝试使用beatle::beatle的任何默认构造函数 错误:

1>  ecosystem.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\map(172): error C2512: 'beatle::beatle' : no appropriate default constructor available
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\map(165) : while compiling class template member function 'beatle &std::map<_Kty,_Ty>::operator [](int &&)'
1>          with
1>          [
1>              _Kty=tokenID,
1>              _Ty=beatle
1>          ]
1>          c:\users\zak\documents\visual studio 2010\projects\ascii_sivvure\ascii_sivvure\ecosystem.h(22) : see reference to class template instantiation 'std::map<_Kty,_Ty>' being compiled
1>          with
1>          [
1>              _Kty=tokenID,
1>              _Ty=beatle
1>          ]

剥离了非相关内容的代码:

头:

typedef std::map<tokenID,beatle>    Beatles;

class ecosystem
{
private:
line 22:    Beatles m_Beatles;
};

源:

ecosystem::ecosystem(): m_output( output() )
{
    Beatles m_Beatles;
}

void ecosystem::populate()
{
    if (m_isMatingSeason && ( random(0,1000) < rateMATING ) )
    {
        beatle babyBeatle = breed();
        m_Beatles[babyBeatle.getTokenID()] = babyBeatle;
        m_field.occupy(babyBeatle.getTokenID(), babyBeatle.getLocation() );
    }
}

我一直在尝试使用不同的组合尝试正确定义/声明maps数小时。有一次intellisense开始说它想要指向对象:

m_Beatles[babyBeatle.getTokenID()] = babyBeatle;

这让我走上了悲伤的道路。

这是在我的第一次(并且希望是最后一次)重构狂欢之后发生的事情,自从我能够编译以来已经过了一个星期...我可能有40个小时只是想让它再次运行。

3 个答案:

答案 0 :(得分:2)

beatle类是否有默认构造函数?在operator[]上使用std::map可以在地图中构建一个条目,如果找不到您提供的密钥,那么它需要能够创建地图值(此处为beatle })。

答案 1 :(得分:2)

由Adam Rosenfield的评论提示更正......

std::map<>::operator[]要求值类型具有公共默认构造函数:如果要使用class beatle中的该函数,则只需在std::map<>中有一个。标准说只要不使用指定默认构造参数的签名调用成员函数(参见下文),就可以创建非默认构造对象的容器,但这实际上不会与std::map<>::operator[]凝聚。使用T()的问题尽管没有在签名中提及它。

  

20.1.4 - 默认构造[lib.default.con.req]

     

-1-不需要默认构造函数。某些容器类成员函数签名将默认构造函数指定为默认参数。如果使用默认参数(dcl.fct.default)调用其中一个签名,则T()必须是定义良好的表达式(dcl.init)。

您问这是否意味着您可以在默认构造函数中保留未初始化的成员变量。是的,只要它们没有说明可能被operator=或析构函数删除的指针 - 您需要将它们显式设置为0 / NULL。如果某些成员变量是具有自己的默认构造函数的对象,那么无论是否需要它们,都可以运行它们(即使它们只是设置整数,双精度等),除非编译时优化能够检测到他们是多余的。

答案 2 :(得分:2)

std::map<>::operator[]需要默认构造函数。这是因为它首先在地图中创建一个条目,然后执行您正在调用的operator=

如果您绝对想要使用std::map但又不想提供默认构造函数(可能对您的案例不合逻辑?),您可以使用:

std::map<>::insert()

将对象显式插入代码中。这使得事情变得更复杂,因为查找还必须使用find。

我刚刚注意到Adam Rosenfield已在评论中发布此信息,但继续将此作为单独的答案。