Weird values in classes.

Started by
10 comments, last by nullsquared 18 years, 7 months ago
Hi! I am having this problem with my classes in my game... For some reaon when I have a constructor that sets the value for the health to 50 or 50 times 2 I get numbers like -2 and 454572987!!!???!!! Heres the code:

#include <iostream>
#include <string>
#include <vector>
#include <cctype>

using namespace std;

class Enemy
{
    public:
           Enemy(int damage = 10, 
                 int defence = 5, 
                 int health = 50): 
                 m_Damage(damage), 
                 m_Defence(defence),
                 m_Health(health) {}
           
           int GetDamage() {return m_Damage;}
           int GetDefence() {return m_Defence;}
           int GetHealth() {return m_Health;}
           int SetHealth(int a)
           {
               m_Health = m_Health - a;
               if (m_Health < 0)
                   m_Health = 0;
           }
           
    private:
            int m_Damage;
            int m_Defence;
            int m_Health;
};

class Fairy: public Enemy
{
    public:
           Fairy(int magic = 20, int stars = 0): 
                     Enemy(Enemy::GetDamage()/2, 
                           Enemy::GetDefence()*2, 
                           Enemy::GetHealth()/2),
                     m_MagicDamage(magic), 
                     m_Stars(stars) {}
           
           int GetStars() {return m_Stars;}
           int GetMagicDamage() {return m_MagicDamage;};
           
    private:
            int m_Stars;
            int m_MagicDamage;
                          
};

class Orc: public Enemy
{
    public:
           Orc(): Enemy(Enemy::GetDamage()*2,
                        Enemy::GetDefence()*2,
                        Enemy::GetHealth()*2) {}
};

class Hero: public Enemy
{
    public:
           Hero(int stars = 0, int specialDamage = 25): 
                    Enemy(Enemy::GetDamage()*2,
                          Enemy::GetDefence()*2,
                          Enemy::GetHealth()*2),
                    m_Stars(stars),
                    m_SpecialDamage(specialDamage) 
           {
               cout<<"\nWhats your hero's name: ";
               string name;
               cin>>name;
               cin.ignore();
               
               name[0] = toupper(name[0]);
               m_Name = name;
           }
           
           int GetStars() {return m_Stars;}
           int GetSpecialDamage() {return m_SpecialDamage;}
           string GetName() {return m_Name;}
           
    private:
            int m_Stars;
            int m_SpecialDamage;
            string m_Name;
};

void displayItems(vector<string> &theInventory, Hero &theHero);
string allToUpper(string word);
bool tipFunc(bool &tip);

int main()
{
    cout<<"\t\t\t     Welcome to HaM!!!\n";
    cout<<"\t\t\t The ultimate adventure!!!\n";
    
    Hero theHero;
    cout<<"\nYou named your hero "<<theHero.GetName()<<".\n";
    
    vector<string> theInventory;
    displayItems(theInventory, theHero);
    
    // Debugging
    cout<<theHero.GetHealth()<<endl;
    Orc orc;
    cout<<orc.GetHealth();
    
    cout<<theHero.GetName()<<" can go in four directions:\n";
    cout<<"1) Up\n2) Down\n3) Left\n4) Right\n";
    
    cout<<"\nEnter the direction or the number: ";
    
    string answer;
    cin>>answer;
    cin.ignore();
    
    answer = allToUpper(answer);
    
    bool tip = false;
    
    while (answer != "2" && answer != "DOWN")
    {
        if (tip == false)
            tipFunc(tip);
            
        if (answer != "1" && 
            answer != "UP" && 
            answer != "3" && 
            answer != "LEFT" && 
            answer != "4" && 
            answer != "RIGHT")
            cout<<"\nPlease enter a choice from 1-4 only.\n";
            
        if (answer == "1" || answer == "UP")
        {
            cout<<endl<<theHero.GetName()<<" fell off a cliff.\n";
            theHero.SetHealth(10);
            cout<<endl<<theHero.GetName()<<"' health: "<<theHero.GetHealth()<<".\n";
        }
        cin.get(); // So the program doesnt end
    }
    
    cin.get();
    return 0;
}

void displayItems(vector<string> &theInventory, Hero &theHero)
{
    vector<string>::iterator iter;
    cout<<"\n"<<theHero.GetName()<<"' items:\n";
    if (theInventory.size() < 1)
        cout<<theHero.GetName()<<" has no items.\n";
    else
        for (iter = theInventory.begin(); iter != theInventory.end(); iter++)
        {
            cout<<*iter<<endl;
        }
    cout<<endl;
}

string allToUpper(string word)
{
    for (int i = 0; i < word.size(); i++)
        word = toupper(word);
        
    return word;
}

bool tipFunc(bool &tip)
{
    cout<<"\nHint: If your health goes down to 0 you lose.\n";
    tip = true;
}


Advertisement
Quote:
Orc(): Enemy(Enemy::GetDamage()*2,             Enemy::GetDefence()*2,             Enemy::GetHealth()*2) {}


You are passing parameters to the base class constructor.
Those parameters are computed from members of the base object.
However, the base object doesn't exist yet - you are constructing it!
Therefore, you really are passing garbage to the constructor.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
So should I like give exact values instead of retrieving them?
The problem is that, when you are calling the Enemy constructor in your derived class's initializer list, you invoke Enemy's member functions BEFORE Enemy has been constructed.

So what you do is
(in Ork::Ork) Enemy::m_Damage=Enemy::m_Damage * 2
but at that point m_Damage is still uninitialized. Garbage in - garbage out. [smile]

[edit]Damn I'm slow...
Quote:Original post by agi_shi
So should I like give exact values instead of retrieving them?


Well, yes - there are no values to retrieve yet.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by agi_shi
So should I like give exact values instead of retrieving them?


Yes. You could use static member variables, for example.

[edit][dead]
Sooo.... Like this? :
[source language="C++"]class Orc: public Enemy{    Orc(): Enemy(20,10,100) {}}
Statics ehh??
Well for now I'll go on testing, thanks.
I'll tell you guys about it here again, so check back now and then.
Or like this

class Enemy{protected:   static const int base_damage=10;   static const int base_defense=5;   static const int base_health=50;public:   Enemy( int damage=base_damage, int defense=base_defense, int health=base_health )     : m_Damage( damage )     , m_Defense( defense )     , m_Health( health )   {}private:   int m_Damage;   int m_Health;   int m_Defense;};class Orc: public Enemy{    Orc( int damage=base_damage*2, int defense=base_defense*2, int health=base_health*2 )       : Enemy(damage, defense, health)     {}};
OH YEAH! Thanks for the great idea... Since I'm a beginner let me explain this to myself and you tell me if I'm right... Since those are statics they arent constructed in the constructor itself... and since they are protected they are acceseble in the inherited classes... correct?

This topic is closed to new replies.

Advertisement