虚函数不起作用

时间:2018-07-11 13:34:24

标签: c++ virtual

此代码未编译。基本类中的虚函数 attack()中的所有问题。

团队班级,还没有足够的机会。我曾尝试做这些班级的朋友。另外,我已经完成了功能ptr,但是它不起作用。

虚拟函数在继承的类中也不起作用。 Visual Studio 2015显示错误:

  

C2228,C2227,C2027。

请帮助。

class Team;
class Unit
{
 protected:
int hp;
int dmg;
int doodge;
 public:
Unit(int hp, int dmg, int doodge): hp(hp), dmg(dmg), doodge(doodge){}
int GetHP()
{
    return hp;
}
void SetHP(int hp)
{
    this->hp = hp;
}
virtual void attack(Team &T)
{
    int id = rand() % 3;
    for (int i = 0; i < 3; i++)
        if (typeid(*this) == typeid(T.arr[i]))
        {
            id = i;
            break;
        }
    if (T.arr[id] <= 0)
        return;
    else
        T.arr[id]->SetHP(T.arr[id]->GetHP() - this->dmg);
 }
};
class Swordsman:public Unit
{
 public:
Swordsman():Unit(15,5,60){}
//virtual void attack(Team & T)override
//{
//  int id = rand() % 3;
//  for (int i = 0; i < 3; i++)
//      if (typeid(Swordsman) == typeid())
//      {
//          id = i;
//          break;
//      }
//  if (*T.arr[id]->GetHP <= 0)
//      return;
//  else
//      *T.arr[id]->SetHP(T.arr[id]->GetHP() - dmg);
//}
};
class Archer :public Unit
{
public:
Archer() :Unit(12, 4, 40) {}
//virtual void attack(Team & T)override
//{
//  int id = rand() % 3;
//  for (int i = 0; i < 3; i++)
//      if (typeid(Archer) == typeid())
//      {
//          id = i;
//          break;
//      }
//  if (*T.arr[id]->GetHP <= 0)
//      return;
//  else
//      *T.arr[id]->SetHP(T.arr[id]->GetHP() - dmg);
//}
};
class Mage :public Unit
{
 public:
Mage() :Unit(8, 10, 30) {}
/*virtual void attack(Team & T)override
{
    int id = rand() % 3;
    for (int i = 0; i < 3; i++)
        if (typeid(*this) == typeid())
        {
            id = i;
            break;
        }*/
};
class Team
{
static short counter;
string name;
Unit* arr[3];
public:
Team()
{
    name = "Team " + counter++;
    for (int i = 0; i < 3; i++)
    {
        int selecter = rand() % 3;
        switch (selecter)
        {
        case 0:
            arr[i] = new Swordsman();
            break;
        case 1:
            arr[i] = new Archer();
            break;
        case 2:
            arr[i] = new Mage();
            break;
        }
    }
}
~Team()
{
    delete[]arr;
}
Unit * ptr(int id)
{
    return arr[id];
}
bool check()
{
    bool res = false;
    for (int i = 0; i < 3; i++)
        if (arr[i]->GetHP() > 0)
            res = true;
    return res;
}
void print()
{
    cout << endl << "\t\t" << name << endl << endl;
    cout << "\t" << typeid(*arr[0]).name() << endl;
    cout << "\t" << typeid(*arr[1]).name() << endl;
    cout << "\t" << typeid(*arr[2]).name() << endl;
}
friend class Unit;
};
short Team::counter = 0;
class Game
{
Team A, B;
public:
int Play()
{
    while (true)
    {
        A.ptr(1)->attack(B);
        if (A.check())
            return 1;
        else if (B.check())
            return 2;

    }
 }
};
int main()
{
       return 0;
}

1 个答案:

答案 0 :(得分:1)

忽略任何不相关的内容:

class Team;
class Unit
{
public:
    virtual void attack(Team &T)
    {
        if(typeid(*this) == typeid(T.arr[i]))
        //                           ^^^
        { }
    }
};

您正在访问类Team的成员,但是在给定的时间,您只提供了Team的声明...旁注:这并不特定于虚函数,但是会会与您编写的任何代码一起发生。

您现在的问题是TeamUnit两个类的函数实现都依赖于另一个类的完整定义。因此,解决该问题的唯一方法是实现类外部的功能之一,例如e。 g。:

class Team;
class Unit
{
public:
    // requires Team, so only declared, not implemented!
    virtual void attack(Team &T);
    //                          ^
};

class Team
{
    // complete definition!
};

void Unit::attack(Team& t)
{
    // now implementation of...
}

另一个小问题是arr成员是私有成员。好吧,您已经提供了一种吸气剂(ptr),所以请使用它(并给它起一个更好的名字...)。

如果您要进一步进行简洁的设计,请将您的部门和团队分成不同的编译单元,每个编译单元都附带一个标头和一个源文件:

unit.h:

class Team;
class Unit
{
    // private members
public:
    // only declarations as above, including constructor/destructor
    // by the way: you are lacking a virtual destructor!!!
    virtual ~Unit();
};

unit.cpp:

#include "unit.h"
#include "team.h" // fetch the definition of Team!

Unit(/*...*/) { }
Unit::~Unit() { }
// function definitions as shown above...

您将对Team甚至您的Unit派生类以及Game类执行相同的操作。但是请注意,如果要继承,则需要完整的类定义,因此您需要在标头中已经包含unit.h:

archer.h:

#include "unit.h"

class Archer : public Unit
{
    // again, only function declarations...
    // as base class has already a virtual destructor, own destructor
    // gets virtual implicitly (even the default one), so if you do
    // not need it, you do not have to define it...
};

archer.cpp:

#include "archer.h"
// and whatever else needed, solely, unit.h already comes with archer.h

// implementations...