Warm tip: This article is reproduced from stackoverflow.com, please click
c++ shared-ptr

`std::shared_ptr`: is not a valid template type argument for parameter `_Ty`

发布于 2020-03-28 23:15:50

Errors

Hero: undeclared identifier

std::shared_ptr: Hero is not a valid template type argument for parameter _Ty

unary ->: std::shared_ptr does not define this operator or a conversion to a type acceptable to the predefined operator

attackInput, getSkill os not a member of std::shared_ptr

void my::Weapon::hit(std::shared_ptr,std::shared_ptr): cannot convert argument 1 from std::shard_ptr<my::Hero> to std::shared_ptr

Source.cpp

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <windows.h>
#include "Hero.h"

void checkLife(my::Hero* hero)
{
    if (hero->is_dead())
    {
        delete hero;
        hero = nullptr;
    }
    if (hero == nullptr)
    {
        srand(time(0));
        int rand = 1 + std::rand() % 40;

        if (rand > 0 && rand <= 10) hero = new my::King();
        else if (rand > 10 && rand <= 20) hero = new my::Queen();
        else if (rand > 20 && rand <= 30) hero = new my::Troll();
        else if (rand > 30 && rand <= 40) hero = new my::Knight();
    }
}

int main()
{
    my::Hero* hero = nullptr;
    my::Hero* enemy = nullptr;

    while (true)
    {
        checkLife(hero);
        checkLife(enemy);

        hero->attackOutput(std::shared_ptr<my::Hero>(enemy));
        enemy->attackOutput(std::shared_ptr<my::Hero>(hero));

        system("cls");
        std::cout << hero->getName() << "`s health - " << hero->getHealth() << std::endl;
        std::cout << hero->getName() << "`s health - " << hero->getHealth() << std::endl;
        Sleep(1000);
    }

    if (hero != nullptr) delete hero;
    if (enemy != nullptr) delete enemy;
    system("pause");
    return 0;
} 

Hero.h

#pragma once
#include <memory>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Weapon.h"

namespace my
{
    class Hero abstract
    {
    protected:
        std::shared_ptr<Weapon> weapon;
        std::string name;
        int health;
        int skill;
        int pressure;
        int nobleness;
        int beauty;

        virtual void attack(int damage)
        {
            srand(time(0));
            this->health -= damage + rand() % 20 - this->getPressurel();
        }
    public:
        Hero(std::string name, int health, int skill, int pressure, int nobleness, int beauty)
        {
            this->name = name;
            this->health = health;
            this->skill = skill;
            this->pressure = pressure;
            this->nobleness = nobleness;
            this->beauty = beauty;
        }
        std::string getName() const
        {
            return this->name;
        }
        int getHealth() const
        {
            return this->health;
        }
        int getSkill() const
        {
            return this->skill;
        }
        int getPressurel() const
        {
            return this->pressure;
        }
        int getNobleness() const
        {
            return this->nobleness;
        }
        int getBeauty() const
        {
            return this->beauty;
        }
        void attackInput(const int damage)
        {
            this->attack(damage);
        }
        void attackOutput(std::shared_ptr<Hero> enemy)
        {
            std::shared_ptr<Hero> thisHero(this);
            this->weapon->hit(std::shared_ptr<Hero>(thisHero), enemy);

        }
        virtual void takeWeapon(std::shared_ptr<Weapon> weapon)
        {
            this->weapon = weapon;
        }
        bool is_dead()
        {
            if (this->health <= 0) return true;
            else return false;
        }
    };

    class King : public Hero
    {
    public:
        King() : Hero("King", 300, 2, 4, 10, 15) {}
    };

    class Queen : public Hero
    {
    public:
        Queen() : Hero("Queen", 300, 2, 4, 10, 15) {}
    };

    class Troll : public Hero
    {
    public:
        Troll() : Hero("Troll", 300, 2, 4, 10, 15) {}
    };

    class Knight : public Hero
    {
    public:
        Knight() : Hero("Knight", 300, 2, 4, 10, 15) {}
    };
}

Weapon.h

#pragma once
#include "Hero.h"

namespace my
{
    class Weapon abstract
    {
    protected:
        const int damage;
        int wear;
    public:
        Weapon(int damage, int weight, int size, int wear) : damage(damage)
        {
            this->wear = wear;
        }
        Weapon() : Weapon(1, 1, 1, 1) {}

        virtual void setWeaponWear(int wear)
        {
            this->wear = wear;
        }
        virtual int getWeaponDamage() const
        {
            return this->damage;
        }
        virtual int getWeaponWear() const
        {
            return this->wear;
        }

        virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy) = 0;
    };

    class Knife : public Weapon // NOZH
    {
    protected:
    public:
        virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
        {
            int damage = this->damage * me->getBeauty();
            this->wear--;
            enemy->attackInput(damage);
        }
    };

    class Bow : public Weapon // LUCK
    {
    protected:
    public:
        virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
        {
            int damage = this->damage * me->getNobleness();
            this->wear--;
            enemy->attackInput(damage);
        }
    };

    class Ax : public Weapon // TOPOR
    {
    protected:
    public:
        virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
        {
            int damage = this->damage * me->getPressurel();
            this->wear--;
            enemy->attackInput(damage);
        }
    };

    class Sword : public Weapon // MECH
    {
    protected:
    public:
        virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
        {
            int damage = this->damage * me->getSkill();
            this->wear--;
            enemy->attackInput(damage);
        }
    };
}
Questioner
Alexander
Viewed
48
Nopileos 2020-01-31 19:02

As pointed out in the comments by @WhozCraig you have a circular dependency. You need Weapon.h in Hero.h and Hero.h in Weapon.h.

The only reason you need Hero.hinWeapon.h. Is for thehit(...)function. The best solution would be to declare the hit function somewhere else. Right now the best place would be to add it to theHero`. A hero has a weapon and attacks with that weapon another hero, a weapon itself can't attack, so just from the semantics it makes more sense to have the hit function inside the hero class.

You can probably get it to compile by splitting the code up into a header (.h) and source file (.cpp) and having a forward declaration of Hero in Weaopon.h. But this will not fix the underlying problem and the design is still flawed and will probably cause even more problems if functionality is extended.