首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >程序正在生成一个"error C4430: missing type specifier - int assumed“。包含有效用户定义对象的Skill.h .h文件中的错误消息

程序正在生成一个"error C4430: missing type specifier - int assumed“。包含有效用户定义对象的Skill.h .h文件中的错误消息
EN

Stack Overflow用户
提问于 2019-02-28 12:15:29
回答 2查看 389关注 0票数 0

在这个程序中,我试图实现的最终目标是以简单的文本模拟器的形式模拟一个名为"Fire Emblem“的游戏。这里的主要功能是通过一个名为Skill的抽象类,然后由定义具有独特效果的特定技能的更具体的子类继承。不幸的是,当程序运行时,尽管Unit是已经定义的对象类型,但在Skill.h .h文件的激活函数中生成了上述错误。我怀疑这可能与头文件的#include顺序有关,但我认为没有其他方法可以改变顺序并破坏功能。有没有一种方法可以避免重新包含.h文件,同时保持我程序中当前拥有的逻辑?另外,我为大量的代码道歉,我不确定要省略哪些部分。

Skill.h

这个类的目的是作为一个抽象类,更具体的技能子类将从这个抽象类继承并实现activate()函数。

代码语言:javascript
复制
#ifndef SKILL_H
#define SKILL_H
#include "Unit.h"

#include <string>
#include <random>

class Skill{
    public:
        Skill(const std::string &skillName);
        void setSkillLikelyHood(int chance);
        int getLikelyHood() const;
        std::string getSkillName() const;

        //this function generates the error messages specified in the title
        virtual void activate(const Unit &player, Unit &enemy ) = 0;
    protected:
        int random(int min, int max);
        int likelyHood;
        std::string skillName;
};

#endif // !1

Skill.cpp

代码语言:javascript
复制
#include "Skill.h"

Skill::Skill(const std::string &skillName) : skillName(skillName) {
}

void Skill::setSkillLikelyHood(int chance){
    likelyHood = chance;
}

int Skill::getLikelyHood() const{
    return likelyHood;
}

std::string Skill::getSkillName() const{
    return skillName;
}

int Skill::random(int min, int max){
    std::random_device seed;
    std::default_random_engine rnGen(seed());
    std::uniform_int_distribution<int> dist(min, max);

    return dist(rnGen);
}

Astra.h

代码语言:javascript
复制
#ifndef ASTRA_H
#define ASTRA_H
#include "Skill.h"

class Astra : public Skill{
    public:
        Astra();
        void activate(const Unit &player, Unit &enemy) override;
};

#endif

Astra.cpp

代码语言:javascript
复制
#include "Astra.h"

Astra::Astra() : Skill("Astra"){

}

void Astra::activate(const Unit &player, Unit &enemy){
    std::cout << player.getName() << " activated " << skillName << " Oh no!\n";

    int damage = player.getDamageDealtToEnemy(enemy);
    for (size_t i = 0; i < 5; i++){

        //if the player lands a hit AND lands a crit, perform the crit against the enemy. 
        if (player.calculateHit(enemy) && player.calculateCriticalHit(enemy)) {
            std::cout << player.getName() << " landed a crit! " << enemy.getName() << " took " << damage << " damage!\n" ;
            enemy.getHp() -= damage;
        }

        //if the player managed to land a hit, but failed to crit, simply land a regular hit.
        else if (player.calculateHit(enemy)) {
            std::cout << player.getName << " dealt " << damage << " damage!\n";
            enemy.getHp() -= damage;
        }

        //otherwise, the player will miss their attack.
        else
            std::cout << "Attack missed!\n";

    }
}

Unit.h

代码语言:javascript
复制
#ifndef UNIT_H
#define UNIT_H

#include "Astra.h"
#include "Weapon.h"
#include <array>
#include <random>
#include <iostream>
#include <memory>

class Unit{
    public:
        Unit(const std::string &name, const Weapon &weapon, const Skill &s);
        ~Unit();
        void levelUp();
        int &getHp();
        void attack(Unit &unit);
        std::string getName() const;
        int getDamageDealtToEnemy(const Unit &enemy) const;
        bool calculateHit(const Unit &enemy) const;
        bool calculateCriticalHit(const Unit &enemy) const;
        friend std::ostream &operator << (std::ostream &os, const Unit &u);
    private:
        int random(int min, int max) const;
        void calculateStats();
        std::string name;
        std::array<int, 7> stats;
        std::array<int, 7> growthRates;
        std::unique_ptr<Skill> skill;
        Weapon weapon;
        int level, hp, avoid, criticalAvoid, hitRate, totalAttack, criticalRate, criticalChance, exp;
        static int turnNumber;
};

#endif

Unit.cpp

代码语言:javascript
复制
#include "Unit.h"

int Unit::turnNumber = 1;


Unit::Unit(const std::string &name, const Weapon &weapon, const Skill &s) : name(name), weapon(weapon), hp(100), level(1), exp(0),
skill(std::make_unique<Skill>()){

    for (int i = 0; i < stats.size(); i++) {
        stats[i] = random(20, 25);
        growthRates[i] = random(55, 80);
    }

    calculateStats();
    skill->setSkillLikelyHood(stats[2] / 2);

}

Unit::~Unit()
{
}

void Unit::levelUp(){
    hp += random(15, 20);

    for (int i = 0; i < stats.size(); i++){
        if (random(0, 100) < growthRates[i])
            stats[i] += random(2, 4);
    }
}

int &Unit::getHp(){
    return hp;
}

//This function
void Unit::attack(Unit &enemy){

    std::cout << "turn: " << turnNumber << "\n";
    std::cout << name << " attacked " << enemy.name << "!\n";

    //On the first turn, and only the first turn (as doing so after the first turn is unnecessary) calculate the player and the
    //enemy's stats after factoring in the weapon triangle bonus.
    if (turnNumber == 1) {
        weapon.determineWeaponTriangleBonus(enemy.weapon.getWeaponType());
        enemy.weapon.determineWeaponTriangleBonus(this -> weapon.getWeaponType());
        calculateStats();
        enemy.calculateStats();
    }

    switch (calculateHit(enemy)){
        int damage;

        //if you manage to land a hit....
        case true:
            //when you land a critical hit, you will deal three times normal damage!
            damage = (calculateCriticalHit(enemy)) ? (totalAttack - enemy.stats[5]) * 3  : (totalAttack - enemy.stats[5]);
            std::cout << name << "'s attack: " << totalAttack << "\n";
            enemy.hp -= damage;
            std::cout << enemy.name << " took " << damage << " damage! HP: " << enemy.hp << "\n\n";
            break; 
        case false:
            std::cout << name << " miss his attack! :(\n\n";
    }

    //base case. When either the player or enemy has died, end the recursive call
    if (enemy.hp <= 0) {
        std::cout << enemy.name << " is dead!\n";
        return;
    }

    turnNumber++;

    enemy.attack(*this);
}

std::string Unit::getName() const{
    return name;
}

int Unit::getDamageDealtToEnemy(const Unit &enemy) const{
    return totalAttack - enemy.stats[5];
}

int Unit::random(int min, int max) const{
    std::random_device seed;
    std::default_random_engine rnGen(seed());
    std::uniform_int_distribution<int> dist(min, max);

    return dist(rnGen);
}

void Unit::calculateStats(){
    int &att = stats[0], &mag = stats[1], &skl = stats[2], &spd = stats[3], &lck = stats[4], &def = stats[5], 
        &res = stats[6];

    avoid = (spd * 2) + lck;
    criticalAvoid = lck / 2;
    hitRate = weapon.getAccuracy() + (skl * 2) + (lck / 2);
    criticalRate = skl + weapon.getCritical();
    totalAttack = att + weapon.getMight();
}

bool Unit::calculateHit(const Unit &enemy)const{
    std::cout << "hit rate: " << hitRate - enemy.avoid << "%\n";
    return ((random(0, 100) + random(0, 100)) / 2) < hitRate - enemy.avoid;
}

bool Unit::calculateCriticalHit(const Unit &enemy) const{
    //std::cout << "critical hit: " << criticalRate - unit.criticalAvoid << "%\n";
    return random(0, 100) < criticalRate - enemy.criticalAvoid;
}

std::ostream & operator<<(std::ostream & os, const Unit & u){
    std::array<std::string, 7> statNames{"att", "mag", "skl", "spd", "lck", "def", "res"};

    std::cout << u.name << "'s hp: " << u.hp << "\n";

    for (int i = 0; i < statNames.size(); i++)
        os << statNames[i] << ": " << u.stats[i] << "\n";

    os << "Avoid: " << u.avoid << "\n";
    os << "hitRate: " << u.hitRate << "\n";
    os << "critical avoid: " << u.criticalAvoid << "\n";
    os << "critical rate: " << u.criticalRate << "\n";

    return os;
}
EN

回答 2

Stack Overflow用户

发布于 2019-02-28 12:43:59

当你在编译Skill类时,编译器并不知道类。要使其可用,您必须对Unity类执行"forward声明“。

在Skill.h .h中的标题后面添加以下行

代码语言:javascript
复制
class Unity;
票数 1
EN

Stack Overflow用户

发布于 2019-02-28 12:56:43

OP有一个循环依赖: Skill.h .h -> Unit.h .h -> Astra.h -> Skill.h.h。

虽然up包含guardians终止递归(否则会引发编译器错误-类似于“太多嵌套的include”),但它以类型使用(在其中一个头中)结束,因为之前的类型定义丢失(由于有效的头guardian)。

应该防止循环依赖。或者,应该使用转发声明。

请注意,要使用指向类型的指针或引用,不完整的类型就足够了(例如class Unit;)。

因此,头部中的声明可能基于转发声明。因此,至少可以移除循环依赖#include中的一个。

然后,三个C++文件中的每一个都可以对所有三个头文件执行#include操作而不会造成损害。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54918322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档