1

I have A base class in this file:

#ifndef MTM_CHARACTER_H_
#define MTM_CHARACTER_H_
#include "Exceptions.h"
#include "Auxiliaries.h"
#include <memory>

namespace mtm
{
    
  class Character
  {
      protected:
              int health
               
      public:
              
             Character(int health): health(health){}
             virtual Character* clone() const = 0;
        
};
}
#endif

and then I have derived class:

#ifndef MTM_SNIPER_H_
#define MTM_SNIPER_H_
#include "Character.h"
#include <memory>
namespace mtm
{
 
 class Sniper: public Character
 {
     private:
            units_t successful_attack;
   public:
    Sniper(int health,units_t successful_attack=0): 
    Character(health), successful_attack(successful_attack){}
    virtual Character* clone() const override
    {
          return  new Sniper(*this) ;
    }
 
};
}
#endif

and no matter what I do I keep getting these errors:

/tmp/cc5TyEEH.o:(.gcc_except_table+0xbc): undefined reference to `typeinfo for mtm::Character'
/tmp/ccbNL933.o: In function `mtm::Character::Character(mtm::Character const&)':
/home/raghad-a/mtm3_3/Character.h:25: undefined reference to `vtable for mtm::Character'
/tmp/ccbNL933.o:(.rodata._ZTIN3mtm5MedicE[_ZTIN3mtm5MedicE]+0x10): undefined reference to `typeinfo for mtm::Character'
/tmp/ccrnaFqr.o:(.rodata._ZTIN3mtm6SniperE[_ZTIN3mtm6SniperE]+0x10): undefined reference to `typeinfo for mtm::Character'
/tmp/ccGBmaWP.o:(.rodata._ZTIN3mtm7SoldierE[_ZTIN3mtm7SoldierE]+0x10): undefined reference to `typeinfo for mtm::Character'
/tmp/ccyu18Hf.o: In function `mtm::Character::Character(int, int, int, int, mtm::Team, mtm::CharacterType)':
/home/raghad-a/mtm3_3/Character.h:23: undefined reference to `vtable for mtm::Character'
collect2: error: ld returned 1 exit status

I looked for every question about this kind of problem in this website and none of them solved the problem.

the way I used Sniper std::shared_ptr<Sniper> ptr(new Sniper(health)); std::shared_ptr<Sniper> other_ptr(new Sniper(health));

the way I used clone: ptr=static_cast<std::shared_ptr<Character>>(other_ptr->clone());

Raea6789
  • 141
  • 1
  • 11
  • 6
    As when you posted similar code yesterday (in my time zone), you haven't provided enough information. Read up on how to provide a [mcve] - which is a small but complete sample of code that *someone else* can use to recreate the symptoms you see. Without that, you're forcing people to guess. My guess, since the linker (not compiler) is not finding key inputs related to the `Character` class, is that you left one of the object files (probably `Character.o`) out when linking. – Peter Jul 02 '20 at 00:56
  • This question's shown code does not meet stackoverflow.com's requirements for a [mre]. This means it's unlikely that anyone here can conclusively answer the question; but only guess at the most. You should [edit] your question to show a minimal example, no more than one or two pages of code (the "minimal" part), that everyone else can cut/paste, compile, run, and reproduce the described issue (the "reproducible" part) ***exactly as shown*** (this includes any ancillary information, like the input to the program). See [ask] for more information. – Sam Varshavchik Jul 02 '20 at 01:07
  • @Peter I could not have left one of the object files of character,, I am using this command line , `g++ -g -std=c++11 -Wall -Werror -pedantic-errors -DNDEBUG *.cpp -o mat` – Raea6789 Jul 02 '20 at 08:37

1 Answers1

0

It looks like you might be instantiating an abstract class (because the virtual method is pure virtual (=0)).

Make sure you're dynamically instantiating virtual types, and not using new Character() - because that names the abstract type.

So don't:

 Character x(.....);

Also don't:

 Character x = Sniper(....); // slicing to abstract base

What is object slicing?

NOTE:

  • you don't initialize team in the constructor, and empty is also unused

Working sample:

Live On Coliru

using units_t = int;
enum class Team {team1};
enum class CharacterType {hulk};

#ifndef MTM_CHARACTER_H_
#define MTM_CHARACTER_H_
//#include "Exceptions.h"
//#include "Auxiliaries.h"
#include <memory>

namespace mtm {

    class Character {
        protected:
            units_t health;
            units_t ammo;
            units_t range;
            units_t power;
            Team team;
            CharacterType character_type;

        public:
            Character(units_t health, units_t ammo, units_t range, units_t power,
                    Team team, CharacterType type)
                : health(health), ammo(ammo), range(range), power(power),
                team(team), character_type(type) {}
            virtual Character* clone() const = 0;
            Character(const Character& character) = default;
    };
} // namespace mtm
#endif

#ifndef MTM_SNIPER_H_
#define MTM_SNIPER_H_
//#include "Character.h"
#include <memory>

namespace mtm {
    class Sniper : public Character {
        private:
            bool empty = false;
            units_t successful_attack = 0;

        public:
            Sniper(units_t health, units_t ammo, units_t range, units_t power,
                    Team team, CharacterType type, bool empty = false,
                    units_t successful_attack = 0)
                : Character(health, ammo, range, power, team, type),
                empty(empty), successful_attack(successful_attack) {}
            virtual Character* clone() const override { return new Sniper(*this); }
            Sniper(const Sniper& sniper) = default;
    };
} // namespace mtm
#endif

int main() {
    std::unique_ptr<mtm::Character> ch;
    ch = std::make_unique<mtm::Sniper>(1,1,1,1,Team::team1,CharacterType::hulk);
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Attempting to instantiate an abstract class generally results in a compilation error, not a linker error. – Peter Jul 02 '20 at 09:10