Classes as parameters error

2019-09-19 02:19发布

问题:

In Weapon.h, when I try and take a class 'Entity*' as a parameter, it says "Syntax error: identifier 'Entity'" when I compile. Additionally when I roll over the text 'target', Visual C++ Express 2010 gives me the text " *target". The Entity class is fine and I'm pretty sure it's included correctly.

(I won't post Player.h as it's unnecessary - see Library.h - but it has a header guard and includes Entity.h)

Library.h:

#ifndef _LIBRARY_
#define _LIBRARY_

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <map>
#include <exception>
#include <sstream>

//file includes
#include "Globals.h"
#include "Player.h"
#include "Exception.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"

//prototypes that require "Library.h"
bool Poglathon(std::vector<std::string>& text,Player *player);
bool PoglathonTown(std::vector<std::string>& text,Player *player);

std::map<std::string,Weapon*> init_weapons(void);
std::map<std::string,Armour*> init_armour(void);
std::map<std::string,Consumable*> init_consumables(void);

#endif //__LIBRARY__

Weapon.h:

#ifndef _WEAPON_H_
#define _WEAPON_H_

#include "Shopable.h"

class Weapon : public Shopable{
private:
    int Damage;
public:
    Weapon(int c,int d,std::string n) : Shopable(c,n),Damage(d){}
    std::string getDesc() const{
        return getName()+"\t"+tostring(Damage)+"\t"+tostring(Cost);
    }
    int getDamage() const{return Damage;}
    int DamageTarget(Entity* target){
        int DamageDealt = 0;
        //do damage algorithm things here
        return DamageDealt;
    }
};

#endif

Shopable.h:

#ifndef _SHOPABLE_H_
#define _SHOPABLE_H_

#include "Library.h"

class Shopable{
protected:
    std::string Name;
    int Cost;
    std::string Description;
public:
    Shopable(int c, std::string n):Cost(c),Name(n){}
    std::string getName() const{return Name;}
    int getCost() const {return Cost;}
    virtual std::string getDesc() const = 0;
};

#endif

Entity.h:

#ifndef _ENTITY_
#define _ENTITY_

#include "Library.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"

class Entity{
public:
    void printStats() const;
    void heal(double health);
    std::string name;
protected:
    //player stats
    double str;     //strength
    double wis;     //wisdom
    double ref;     //reflex
    double hp;      //health points
    double maxHp;   //maximum health points
    double i;       //initiative
    double inte;    //intelligence
    double c;       //courage
    int gold;       //gold
    int xp;         //experience
    int ap;         //armour points
    int wd;         //weapon damage
    int lvl;        //level
    int sp;         //skill points
    Weapon* weapon;//weapon
    Armour* cArmour;//current armour
};

#endif

回答1:

Your headers include each other because your classes refer to each other. (But your compiler doesn't suffer from a stackoverflow because of your include guards - that's a good thing!)

You should arrange your header files hierarchically, ie there are files at the 'top' which #include nothing and files 'below' which include some of the top ones and so-on down the hierarchy. But at no point should there be 'loops'.

In order to break your loops in your code, any classes that refer to each other should forward declare any mutual dependencies and only refer to dependency names and not their members.

e.g.

Entity.h

class Weapon;
class Entity{
    ...
    Weapon* weapon;
};

Weapon.h

class Entity;
class Weapon{
    ...
    int DamageTarget(Entity* target);
};

Notice how Weapon.h only refers to Entity*.

You will need to define int Weapon::DamageTarget(Entity* target) in Weapon.cpp



回答2:

In C++, classes must be declared before they are referenced. You are #include-ing Weapon.h in Entity.h, but at that point, the compiler doesn't know about the existence of class Entity.

You will either need to change the order in which things are declared, or add a forward declaration "above" class Weapon. It can simply be:

class Entity;

That tells the compiler that there is such a name as Entity. However, it doesn't tell it anything about what members it has, so you can't actually do anything with it, other than declare variables of Entity * and Entity &, and pass them around.



回答3:

#include <entity.h>

Or forward-declare only in the header

class Entity;

This makes compilation a bit faster (you still need to include it to use in the implementation).



回答4:

Weapon.h doesn't #include Entity.h, or anything that recursively includes it. Therefore, it doesn't know about the class Entity.