probleme mit klassen in C++, Linker will nicht mitmachen (visual C++ 2005 express)



  • Hi,
    habe ein Problem, wollte ein bischen üben mit Klassen zu programmieren, aber irgendwie mache ich etwas falsch, oder visual C++ 2005 express spinnt total..
    Ich bekomme ein paar Fehler beim linken:

    ------ Erstellen gestartet: Projekt: Klasse fighter, Konfiguration: Release Win32 ------
    Kompilieren...
    main.cpp
    fighter.cpp
    Code wird generiert...
    Verknüpfen...
    main.obj : error LNK2005: "public: bool __thiscall Fighter::init(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int,int,int,int)" (?init@Fighter@@QAE_NABV?basic_string@DU?basic\_string@DU?char_traits@D@std@@V?$allocator@D@2@@std@@HHHH@Z) ist bereits in fighter.obj definiert.
    main.obj : error LNK2005: "public: bool __thiscall Fighter::takeDmg(int)" (?takeDmg@Fighter@@QAE_NH@Z) ist bereits in fighter.obj definiert.
    main.obj : error LNK2005: "public: void __thiscall Fighter::heal(void)" (?heal@Fighter@@QAEXXZ) ist bereits in fighter.obj definiert.
    main.obj : error LNK2005: "public: void __thiscall Fighter::display(void)" (?display@Fighter@@QAEXXZ) ist bereits in fighter.obj definiert.
    F:\VisualC++\projects\Klasse fighter\Release\Klasse fighter.exe : fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden.
    Das Buildprotokoll wurde unter "file://f:\VisualC++\projects\Klasse fighter\Klasse fighter\Release\BuildLog.htm" gespeichert.
    Klasse fighter - 5 Fehler, 0 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    In meinem Code kann ich jedenfalls keine Fehler finden, mMn. müsste das eigentlich funktionieren...
    hier mal mein Code, wäre nett wenn es jemand versuchen könnte zu kompilieren.

    fighter.h

    //fighter.h
    #ifndef _FIGHTER_
    #define _FIGHTER_
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Fighter
    {
    private:
    	int life;
    	int maxlife;
    	int mana;
    	int maxmana;
    	int defence;
    	int dmg;
    	string name;
    
    public:
    	bool init(const string&,int,int,int,int);
    	bool takeDmg(int);
    	void display();
    	void heal();
    };
    #endif
    

    fighter.cpp

    //fighter.cpp
    #include <iostream>
    #include "fighter.h"
    using namespace std;
    
    bool Fighter::init(const string& i_name,int	i_maxlife,int i_maxmana,int i_defence,int i_dmg)
    {
    	if(i_name.size() < 1)
    		return false;
    	name = i_name;
    	maxlife = i_maxlife;
    	maxmana = i_maxmana;
    	life = maxlife;
    	mana = maxmana;
    	defence = i_defence;
    	dmg = i_dmg;
    	return true;
    }
    
    bool Fighter::takeDmg(int a)
    {
    	a = a - defence;
    	if(a<0)
    		a=0;
    	life = life - a;
    	if(life<=0)
    		return false;
    	return true;
    }
    
    void Fighter::heal()
    {
    	life = maxlife;
    	mana = maxmana;
    }
    
    void Fighter::display()
    {
    	cout<<"name: "<<name<<endl;
    	cout<<"life: "<<life<<" / "<<maxlife<<endl;
    	cout<<"mana: "<<mana<<" / "<<maxmana<<endl;
    	cout<<"defence: "<<defence<<endl;
    	cout<<"damage: "<<dmg<<endl;
    }
    

    main.cpp

    //main.cpp
    #include "fighter.cpp"
    
    int main()
    {
    	Fighter Cloud,Leon;
    	Cloud.init("Cloud",1000,100,50,300);
    	Leon.init("Leon",2000,100,10,165);
    	Cloud.display();
    	Leon.display();
    	return 0;
    }
    

    Danke im Voraus.



  • Sabjosu schrieb:

    ...

    ...
    main.obj : error LNK2005: .... ist bereits in fighter.obj definiert.
    ...

    Recht hat er:

    Sabjosu schrieb:

    ...

    //main.cpp
    #include "fighter.cpp"
    ...
    

    Da meintest Du bestimmt "...hpp"

    Gruß,

    Simon2.

    P.S. CPP-Tags sind für uns deutlich einfacher zu lesen.



  • // fighter.hpp
    #ifndef FIGHTER_HPP__INCLUDED
    #define FIGHTER_HPP__INCLUDED
    
    #include <string>
    #include <utility>
    #include <iostream>
    
    // using namespace std; nie im Header
    
    class Fighter
    {
        std::pair <unsigned int, unsigned int> m_life;
        std::pair <unsigned int, unsigned int> m_mana;
        unsigned int m_defence;
        unsigned int m_demage;
        std::string m_name;
    
    public:
        Fighter(std::string const& name, unsigned max_life, unsigned int max_mana, unsigned int defence, unsinged int demage)
            : m_name(name), m_life(std::make_pair(max_life, max_life)), m_mana(std::make_pair(max_mana, max_mana)), m_defence(defence), m_demage(demage)
        {} 
    
        friend std::ostream& operator<<(std::ostream& out, Fighter const& data)
        { return (out << "name: " << data.m_name << "\nlife: " << data.m_life.first << " / " << data.m_life.second << "\nmana: " << data.m_mana.first << " / " << data.m_mana.second << "\ndefence: " << data.m_defence << "\ndamage: " << m_demage); }
    
    public:
        bool take_demage(unsigned int);
        void heal();
    };
    
    #endif // FIGHTER_HPP__INCLUDED
    
    // fighter.cpp
    #include "fighter.hpp"
    
    bool Fighter::take_demage(const unsigned int demage)
    {
        const int value(demage - m_defence);
        if (value <= 0 && m_life.first) return true;
    
        m_life.first -= value;
        return m_life.first != 0;    
    }
    
    void Fighter::heal()
    {
        m_life.first = m_life.second;
        m_mana.first = m_mana.second;
    }
    
    // main.cpp
    #include "fighter.hpp"
    #include <iostream>
    
    int main()
    {
        Fighter cloud("Cloud", 1000, 100, 50, 300);
        Fighter leon("Leon", 2000, 100, 10, 165);
        std::cout << cloud << "\n" << leon << std::endl;
    }
    

    und schon ist es ordentlich 🙂



  • Übrigens: die 'init'-Methode ist unsinnig. Für sowas gibt es in C++ Konstruktoren. Erstell also statt der Methode einen geeigneten Konstruktor.



  • Danke, musste wirklich die fighter.hpp und nicht die fighter.cpp includen.
    @(D)evil und Konrad Rudolph:
    thx für die tipps, habe aber gerade erst mit Klassen angefangen und will nichts überspringen (alles der Reihe nach, wie es im schlauen Buch steht *g*)
    @(D)evil warum eigentlich kein "using namespace std;" in einem Header?
    In meinem Buch benutzt der Autor nähmlich auch using namespace std in Header.
    ("C++ Lernen und professionell anwenden", ich hoffe ich habe nichts falsches gekauft.^^)



  • Such mal danach hier im Forum 😉 Dadurch dass das im Header steht, gilt das ja auch für die Dateien, die den Header einbinden ... (so als Tipp) und dann guck dir mal an, wofür Namensräume eigtl. da sind 😉



  • Sabjosu schrieb:

    ("C++ Lernen und professionell anwenden", ich hoffe ich habe nichts falsches gekauft.^^)

    Doch, da hast Du leider offensichtlich etwas Falsches gekauft. Das Buch ist Müll.



  • Tja, gibt leider viele schlechte Bücher. 😞 Aber wenn mann sich hier im Forum rumtreibt, kann man aber das ganze wieder ausgleichen. Vieles wird einem hier richtig gestellt... wie man an diesem Thread hier sieht. 🙂 Wobei es auch viele Threads gibt, wo viel Mist erzählt wird. 😉


Anmelden zum Antworten