报错1:
E:\project\qt\Pokemon3\PokemonServer\pokemon.cpp:470: error: specialization of ‘Race::Race() [with int N = 0]’ after instantiation
Race<0>::Race() : PokemonBase(ATK)
^
报错2:
explicit specialization of ‘Race’ after instantiation
implicit instantiation first required here
instantiation 实例化
specialization 特殊化/具体化
错误原因:显示具体化放在实例化之后,这里首先需要隐式实例化
查阅资料后了解到:
显式具体化声明在关键字 template后面包含<>,而显式实例化没有。
源码 pokemon.h
template <int N>
class Race : public PokemonBase
{
public:Race();virtual ~Race() = default;bool attack(Pokemon& attacker, Pokemon& aim, string& msg, int skillIndex = 0) const;
};源码pokemon.cpptemplate <>
Race<0>::Race() : PokemonBase(ATK)
{// _raceName = "Charmander";_raceName = "小火龙";_expCurve[0] = 5;for (int i = 1; i < 14; ++i){_expCurve[i] = _expCurve[i - 1] + 5 * i;}_skillName[0] = "撞击";_skillName[1] = "火花";_skillName[2] = "怒气";_skillName[3] = "火球";_skillDscp[0] = "普通攻击";_skillDscp[1] = "忽略敌人一半防御的攻击";_skillDscp[2] = "增加攻击力";_skillDscp[3] = "伤害很高的大招";_pp[0] = 10;_pp[1] = 3;_pp[2] = 5;
}template <>
bool Race<0>::attack(Pokemon& attacker, Pokemon& aim, string& msg, int skillIndex) const
{// dbout << attacker.name() << " uses " << attacker.skillName(skillIndex) << "!\n";msg += attacker.skillName(skillIndex) + ' ';switch (skillIndex){case 1: //spark{if (dodge(attacker.cspeed(), aim.cspeed(), msg))return false;int dmg = attacker.catk() + attacker.lv() * 2 - aim.cdef() / 2 + f(4);// return aim.takeDamage(dmg);bool result = aim.takeDamage(dmg);msg += to_string(aim.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(aim.cpp(i)) + ' ';}msg += to_string(attacker.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(attacker.cpp(i)) + ' ';}return result;break;}case 2: //ragemsg += "0 "; // can not dodgeattacker.changeAtk(attacker.atk() / 8);msg += to_string(aim.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(aim.cpp(i)) + ' ';}msg += to_string(attacker.hp()) + " 2 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(attacker.cpp(i)) + ' ';}break;case 3: //fireball{if (dodge(attacker.cspeed(), aim.cspeed(), msg))return false;int dmg = attacker.catk() * 1.5 - aim.cdef() + 8 + f(4 + attacker.lv());bool result = aim.takeDamage(dmg);msg += to_string(aim.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(aim.cpp(i)) + ' ';}msg += to_string(attacker.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(attacker.cpp(i)) + ' ';}return result;break;}default:{//普通攻击if (dodge(attacker.cspeed(), aim.cspeed(), msg))return false;int dmg = attacker.catk() - aim.cdef() + f(4);bool result = aim.takeDamage(dmg);msg += to_string(aim.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(aim.cpp(i)) + ' ';}msg += to_string(attacker.hp()) + " 1 1 1 ";for (int i = 0; i < 3; ++i){msg += to_string(attacker.cpp(i)) + ' ';}return result;break;}} //switchreturn false;
}
//共实例化了四个类,不一一例举
调用优先级:普通函数>显式具体化>显式实例化>普通模版
也就是具体化应该在实例化之前,我做的是具体化,之前的实例化在哪?
发现在以上程序前还有这样一段代码:
PokemonBase* Race0 = new Race<0>();
PokemonBase* Race1 = new Race<1>();
PokemonBase* Race2 = new Race<2>();
PokemonBase* Race3 = new Race<3>();const PokemonBase* Pokemon::races[] = {Race0,Race1,Race2,Race3};
我们可以回到本源上思考,模板类是减少代码量而产生,模板类定义了,真正的类还没有定义,既然没有定义,新建也就无从谈起
解决方案是将后一段代码移植到前一段代码下方,问题解决。