Multiple definition error

Started by
3 comments, last by Aardvajk 8 years, 6 months ago

This is really starting to annoy me, whenever I "include" my header file in any of my .cpp files then I get this error:


||=== Build: Debug in Game (compiler: GNU GCC Compiler) ===|
obj\Debug\unithandler.o||In function `ZNSs4_Rep10_M_disposeERKSaIcE':|
C:\mingw32\i686-w64-mingw32\include\c++\bits\basic_string.h|245|multiple definition of `Object::ObjectID'|
obj\Debug\main.o:C:\Games\MYGAMES\TotalWar\main.cpp|8|first defined here|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|

My header file:


#ifndef UNITHANDLER_HPP
#define UNITHANDLER_HPP

#include <map>
#include <string>
#include <fstream>
#include <SFML/Graphics.hpp>

class DataHandler
{
    public:
        DataHandler();
        void ReadGameData();
};

class Object
{
    public:
        static int ObjectID;
        Object();
        ~Object();
    private:
        int ID = 0;
        int POS_X;
        int POS_Y;
        int HP;
        int DMG;
        std::string DMG_TYPE;
        std::string TYPE;
        float FUEL;
        float AMMO;
        float MOVES;
        int STATUS = 0;

        void SetProperty(std::string property_type, std::string new_value);
        void SetSprite(sf::Sprite sprite);
        void Draw();

        void Move();
        void Attack(int x, int y);
        int GetMoves();
        int GetHP();
};

class ObjectHandler : public Object
{
    public:
        static int ObjectID;
        ObjectHandler();
        void Add();
        void Remove(int id);
    private:
        std::vector<Object*> ActiveObjects;
};

int Object::ObjectID = 0;

ObjectHandler Obj;

void UpdateObjects();

void DrawObjects();
#endif

Help please.

Thanks in advance...

Advertisement

Your definition of Object::ObjectID should be within a source file. Currently if you include your header file in multiple .cpp files the compiler will generate multiple instances of the ObjectID as you have it currently defined "int Object::ObjectID = 0"

On a side note I'm not entirely certain how the compiler handles two declarations of a static with the same name in a base class and the derived class as well.


int Object::ObjectID = 0;

This line needs to go in a .cpp file, not a .h file.

Otherwise, every single .cpp that #includes the .h will create its own copy of 'Object::ObjectID', which will define it multiple times (hence "multiple definition" as an error).

You can declare variables multiple times, but there must be only one authoritative definition.

The differences between declarations and definitions are subtle, but important thing to learn.

Likewise:


ObjectHandler Obj;

This should also be in a .cpp file, and perhaps declared 'extern' in the header, if it truly must be global.

[Edit:]


On a side note I'm not entirely certain how the compiler handles two declarations of a static with the same name in a base class and the derived class as well.

Good catch, I missed that.

The answer is, both are different variables.

One is named Object::ObjectID, and the other is named ObjectHandler::ObjectID. Their namespace (or in this case, their class's name), is part of their actual name. The compiler would probably compile it to something conceptually like: _ZN6object9objectidE and _ZN13objecthandler9objectidE, as the invisible internal name the compiler uses.

So that's probably not what the OP intended.

Thanks so much guys! :D, I added:


extern int Object::ObjectID = 0;
extern ObjectHandler obj; 

In the .cpp file and now it doesn't give me errors :D

Though, it gave me a warning.


||=== Build: Debug in TotalWar (compiler: GNU GCC Compiler) ===|
C:\Games\MYGAMES\TotalWar\unithandler.cpp|3|warning: 'ObjectID' initialized and declared 'extern'|
||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 2 second(s)) ===|

Should I be worried about that? or no?

You don't need the extern in the cpp. Extern means "this is defined somewhere else".

This topic is closed to new replies.

Advertisement