Inheritance trouble

This is a discussion on Inheritance trouble within the C++ Programming forums, part of the General Programming Boards category; I'm trying to learn about inheritance, and now I'm having trouble accesing iherited variables. Code: #include <iostream> using namespace std; ...

  1. #1
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80

    Inheritance trouble

    I'm trying to learn about inheritance, and now I'm having trouble accesing iherited variables.

    Code:
    #include <iostream>
    
    using namespace std;
    
    class Enemy
    {
    public:
           Enemy(): hp(20), sp(0), flee(50), hit(50), atkPower(8) {};
           
           void atk();
           void takeDmg();
           
    protected: 
              int hp;
              int sp;
              int flee;
              int hit;
              int atkPower;
          
    };
    
    class Defiler : public Enemy
    {
    public:
          Defiler(){hp = 30, sp = 10, flee = 60, hit = 60, atkPower = 8;};
          
          void defileAtk();
    private:
            int defileMultiply;      
    };
    
    int main()
    {
        Defiler defOne;
        cout << defOne.hp;
        Enemy noOne;
        cout << endl << noOne.hp;
        cin.get();
    return 0;    
    }
    unless I make all the Enemy class variables public, I can't seem to acces them from defiler. Could anyone tell me what the problem is?

  2. #2
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    It's not that you can't access them from Defiler; you can't access them from main(). You haven't provided any public function to access the protected members.

    Add this as a public method of Enemy:
    Code:
           int get_hp(){return hp;}
    and change main() to this:
    Code:
    int main()
    {
        Defiler defOne;
        cout << defOne.get_hp();
        Enemy noOne;
        cout << endl << noOne.get_hp();
        cin.get();
    return 0;    
    }
    and you'll see that your constructor is doing what you expected.

  3. #3
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    1) Every object is created with a constructor.

    2) Every base class portion of a derived class object is created with a base class constructor. When a derived class constructor is called, the first thing that happens is that a base class constructor is called to construct the base class portion of the derived object.

    The way you have your code now, when a Defiler object is constructed, since you do not explicitly call a base class constructor, the default base class constructor is called automatically. Your default base class constructor creates the base class portion of the derived object with these values:

    Enemy(): hp(20), sp(0), flee(50), hit(50), atkPower(8) {};

    but then you immediately change those values to:

    Defiler(){hp = 30, sp = 10, flee = 60, hit = 60, atkPower = 8;};

    That's inefficient. You should define another constructor in the base class that accepts parameters:

    Code:
    Enemy(int num1, int num2, int num3, int num4, int num5):
             hp(num1), sp(num2), flee(num3), hit(num4), atkPower(num5)
    {
    }
    Then call that from your derived class constructor:
    Code:
    class Defiler : public Enemy
    {
    public:
    	Defiler() : Enemy(30, 10, 60, 60, 8)
    	{
    	}
    However, I think you may be getting confused with the difference between default constructors and constructors that take parameters. To keep it simple, try defining your default constructor to just set all the variables equal to zero:
    Code:
    #pragma warning ( disable : 4786 )
    #include <iostream>
    
    using namespace std;
    
    class Enemy
    {
    public:
    	Enemy():hp(0), sp(0), flee(0), hit(0), atkPower(0) 
    	{
    	}
    
    	Enemy(int num1, int num2, int num3, int num4, int num5): 
    			hp(num1), sp(num2), flee(num3), hit(num4), atkPower(num5)
    	{
    	}
           
    	void atk();
    	void takeDmg();
    
    	int get_hp()
    	{
    		return hp;
    	}
           
    protected: 
    	int hp;
    	int sp;
    	int flee;
    	int hit;
    	int atkPower;
    
    };
    
    class Defiler : public Enemy
    {
    public:
    	Defiler(): Enemy(), defileMultiply(0)
    
    	{
    	}
    	
    	Defiler(int dM, int num1, int num2, int num3, int num4, int num5):
    			Enemy(num1, num2, num3, num4, num5), 
    			defileMultiply(dM)
    	{
    	}
         
    	void dfileAtk();
    
    	int get_defileMultiply()
    	{
    		return defileMultiply;
    	}
    
    private:
    	int defileMultiply;      
    };
    
    int main()
    {
    	Defiler defOne(9999,30,10,60,60,8);
    	cout << defOne.get_hp()<<endl;
    	cout<<defOne.get_defileMultiply();
    
    	Enemy noOne;
    	cout << endl << noOne.get_hp();
    
    	cin.get();
    	
    	return 0;    
    }
    All the intializer lists can make things confusing too, so you may want to make things even simpler:
    Code:
    #include <iostream>
    
    using namespace std;
    
    class Enemy
    {
    public:
    	Enemy()
    	{
    		hp = sp = flee = hit = atkPower = 0;
    	}
    
    	Enemy(int num1, int num2, int num3, int num4, int num5) 
    	{
    		hp = num1;
    		sp = num2;
    		flee = num3;
    		hit = num4;
    		atkPower = num5;
    	}
           
    	void atk();
    	void takeDmg();
    
    	int get_hp()
    	{
    		return hp;
    	}
           
    protected: 
    	int hp;
    	int sp;
    	int flee;
    	int hit;
    	int atkPower;
    
    };
    
    class Defiler : public Enemy
    {
    public:
    	Defiler(): Enemy()
    
    	{
    		defileMultiply = 0;
    	}
    	
    	Defiler(int dM, int num1, int num2, int num3, int num4, int num5):
    			Enemy(num1, num2, num3, num4, num5) 
    			
    	{
    		defileMultiply = dM;
    	}
         
    	void dfileAtk();
    
    	int get_defileMultiply()
    	{
    		return defileMultiply;
    	}
    
    private:
    	int defileMultiply;      
    };
    
    int main()
    {
    	Defiler defOne(9999,30,10,60,60,8);
    	cout << defOne.get_hp()<<endl;
    	cout<<defOne.get_defileMultiply();
    
    	Enemy noOne;
    	cout << endl << noOne.get_hp();
    
    	cin.get();
    	
    	return 0;    
    }
    Last edited by 7stud; 04-01-2006 at 03:19 PM.

  4. #4
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80
    Thanks guys. I got my getHp function to work and decided to not set any values in the base class and just set values in the derived classes. Don't know if that's effecient?

    This is what my code looks like now.

    Code:
    #include <iostream>
    
    using namespace std;
    
    class Enemy
    {
    public:
           
           void atk();
           void takeDmg();
           
           int getHp(){return hp;}
           int getSp(){return sp;}
           int getFlee(){return flee;}
           int getHit(){return hit;}
           int getAtkPower(){return atkPower;}
           
           void setHp(int HP){hp = HP;}
           void setSp(int SP){sp = SP;}
           void setFlee(int FLEE){flee = FLEE;}
           void setHit(int HIT){hit = HIT;}
           void setAtkPower(int ATKPOWER){atkPower = ATKPOWER;}
                  
    protected:
    
              int hp;
              int sp;
              int flee;
              int hit;
              int atkPower;
          
    };
    
    class Defiler : public Enemy
    {
    public:
    
          Defiler()
          {hp = 30, sp = 10, flee = 60, hit = 60, atkPower = 8, dMultiply = 2;};
          
          void defileAtk();
    
    private:
    
            int dMultiply;      
    };
    
    class Blood : public Enemy
    {
    public:
          Blood()
          {hp = 35, sp = 10, flee = 50, hit = 70, atkPower = 8, bMultiply = 2;};
          
          void bloodAtk();
          
    private:
            int bMultiply;      
    };
    
    class Violence : public Enemy
    {
    public:
          Violence()
          {hp = 50, sp = 20, flee = 70, hit = 80, atkPower = 8, vMultiply = 3;};
          
          void ViolenceAtk1();
          
    private:
            int vMultiply;      
    };
    
    int main()
    {
        Defiler defOne;
        cout << defOne.getHp();
        Blood noOne;
        cout << endl << noOne.getHp();
        noOne.setHp(10);
        cout << endl << noOne.getHp();
        cin.get();
    return 0;    
    }
    Now for the functions

  5. #5
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80
    I need more help. I'm having trouble with the atk() function.

    Code:
    class Hero
    {
    public:
           //Hero(){};
           
           void atk(&Enemy);
           void takeDmg();
           
           int getHp(){return hp;}
           int getSp(){return sp;}
           int getFlee(){return flee;}
           int getHit(){return hit;}
           int getAtkPower(){return atkPower;}
           
           void setHp(int HP){hp = HP;}
           void setSp(int SP){sp = SP;}
           void setFlee(int FLEE){flee = FLEE;}
           void setHit(int HIT){hit = HIT;}
           void setAtkPower(int ATKPOWER){atkPower = ATKPOWER;}
                  
    protected:
              
              int hp;
              int sp;
              int flee;
              int hit;
              int atkPower;
          
    };
    
    void Hero::atk(&Enemy)
    {
               int fleeRoll, flee, hit;
               flee = *Enemy.getFlee();
               hit = *Hero.getHit();
               fleeRoll = flee - hit;   
    }
    Still really confused about pointers and references

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    I got my getHp function to work and decided to not set any values in the base class and just set values in the derived classes.
    Ok, but just so you know, since you didn't define a constructor in the base class, the compiler supplies your class with a default constructor that does nothing but create a base object. Since all objects must be created with a constructor, if the compiler didn't supply your class with a default constructor and you didn't define one, you wouldn't be able to create any objects of the class. The default constructor which is supplied by the compiler when you don't define a constructor for you class looks like this:
    Code:
    Enemy()
    {
    }
    Specifically, the supplied default constructor does not set any member variables equal to any values, so the member variables will contain junk values.

    As I stated before, when a derived constructor is called, the first thing it does is call a base constructor. Since you didn't specify which base constructor to call in your derived class constructor, the default base class constructor is called. The important point is: a base constructor is called whether you explicitly list one in the derived constructor or not.
    Last edited by 7stud; 04-01-2006 at 07:12 PM.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    void atk(&Enemy);

    You have to list the type of the parameter in your function declaration, and '&Enemy' is not a type. Maybe you mean 'Enemy&'. That says the type is 'a reference to an Enemy object'. However, you should realize you have not stated a variable name. It's equivalent to this:

    void atk(int);

    That's legal in a function declaration, but in the function definition, you also have to list a variable name, which is the name you will use inside the function, e.g.:
    Code:
    void atk(int num)
    {
         cout<<num<<endl;
    }
    or
    Code:
    void atk(Enemy& anEnemy)
    {
        cout<<anEnemy.get_hp()<<endl;
    }
    Last edited by 7stud; 04-01-2006 at 07:20 PM.

  8. #8
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80
    Thanks alot. Works now

    Any help is much appreciated.
    Last edited by stillwell; 04-01-2006 at 07:27 PM.

  9. #9
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Still really confused about pointers and references
    (see my previous post, which I think you missed)

    You can think of a reference as an alias or nickname for another variable. Both the nickname and the original variable will refer to the same value. For instance,
    Code:
    int Robert = 10;
    int& Bobby = Robert; //Bobby is 'a reference to an int', i.e. an alias
    		     //for another int
    will result in this:
    Code:
            10
          /    \
         /      \
        /        \
    Robert      Bobby
    Then you can use one variable to change the value that they both refer to:
    Code:
    Bobby = 20;
    which results in:
    Code:
     20
          /    \
         /      \
        /        \
    Robert      Bobby
    So, if you output the value of either Robert or Bobby, you will get 20:
    Code:
    cout<<Robert<<endl;

  10. #10
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80
    Ok, now I've devided my classes into a project with header files.

    Now I've run into a new problem

    This is how my code looks now.

    Hero.cpp
    Code:
    #include <iostream>
    #include <cstdlib>
    #include <time.h>
    
    #include "Enemy.h"
    #include "Hero.h"
    
    using namespace std;
    
    void Hero::atk(Enemy& anEnemy, Hero& aHero)
    {
               int fleeRoll, fleeRoll2;
               
               fleeRoll = (anEnemy.getFlee() - aHero.getHit() );
               
               time_t seconds;
               time(&seconds);
               srand((unsigned int) seconds);
    
               fleeRoll2 = rand() % 100;
               
               if(fleeRoll >= fleeRoll2)
               cout << "\nYou Miss !!";
               else
               cout << "\nYou Hit !!";
    
      
    }
    Enemy.cpp
    Code:
    #include <iostream>
    #include <cstdlib>
    #include <time.h>
    
    #include "Hero.h"
    #include "Enemy.h"
    
    using namespace std;
    
    void Enemy::atk(Hero& aHero, Enemy& anEnemy)
    {
               int fleeRoll, fleeRoll2;
               
               fleeRoll = (aHero.getFlee() - anEnemy.getHit() );
               
               time_t seconds;
               time(&seconds);
               srand((unsigned int) seconds);
    
               fleeRoll2 = rand() % 100;
               
               if(fleeRoll >= fleeRoll2)
               cout << "\nYou Flee !!";
               else
               cout << "\nYou were Hit !!";
    
      
    }
    Hero.h
    Code:
    #ifndef HERO_H
    #define HERO_H
    
    #include <iostream>
    
    #include "Enemy.h"
    
    class Hero
    {
    public:
           
           void atk(Enemy& anEnemy, Hero& aHero);
           void takeDmg();
           
           int getHp(){return hp;}
           int getSp(){return sp;}
           int getFlee(){return flee;}
           int getHit(){return hit;}
           int getAtkPower(){return atkPower;}
           
           void setHp(int HP){hp = HP;}
           void setSp(int SP){sp = SP;}
           void setFlee(int FLEE){flee = FLEE;}
           void setHit(int HIT){hit = HIT;}
           void setAtkPower(int ATKPOWER){atkPower = ATKPOWER;}
                  
    protected:
              
              int hp;
              int sp;
              int flee;
              int hit;
              int atkPower;
          
    };
    
    class Warrior : public Hero
    {
    public:
           
          Warrior()
          {hp = 100, sp = 10, flee = 120, hit = 100, atkPower = 8, wMultiply = 2;};
          
          void warriorAtk();
          
    private:
            
            int wMultiply;      
    };
    
    class Assasin : public Hero
    {
    public:
           
          Assasin()
          {hp = 80, sp = 15, flee = 160, hit = 60, atkPower = 8, aMultiply = 2;};
          
          void assasinAtk();
          
    private:
            
            int aMultiply;      
    };
    
    class Wizard : public Hero
    {
    public:
           
          Wizard()
          {hp = 60, sp = 40, flee = 120, hit = 60, atkPower = 4, wMultiply = 8;};
          
          void magicAtk();
          
    private:
            
            int wMultiply;      
    };
    
    #endif
    Enemy.h
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
           void takeDmg();
           
           int getHp(){return hp;}
           int getSp(){return sp;}
           int getFlee(){return flee;}
           int getHit(){return hit;}
           int getAtkPower(){return atkPower;}
           
           void setHp(int HP){hp = HP;}
           void setSp(int SP){sp = SP;}
           void setFlee(int FLEE){flee = FLEE;}
           void setHit(int HIT){hit = HIT;}
           void setAtkPower(int ATKPOWER){atkPower = ATKPOWER;}
                  
    protected:
              
              int hp;
              int sp;
              int flee;
              int hit;
              int atkPower;
          
    };
    
    
    
    class Defiler : public Enemy
    {
    public:
           
          Defiler()
          {hp = 30, sp = 10, flee = 120, hit = 60, atkPower = 8, dMultiply = 2;};
          
          void defileAtk();
          
    private:
            
            int dMultiply;      
    };
    
    class Blood : public Enemy
    {
    public:
           
          Blood()
          {hp = 35, sp = 10, flee = 110, hit = 70, atkPower = 8, bMultiply = 2;};
          
          void bloodAtk();
          
    private:
            
            int bMultiply;      
    };
    
    class Violence : public Enemy
    {
    public:
           
          Violence()
          {hp = 50, sp = 20, flee = 130, hit = 80, atkPower = 8, vMultiply = 3;};
          
          void ViolenceAtk1();
          
    private:
            
            int vMultiply;      
    };
    
    #endif
    main.cpp
    Code:
    #include <iostream>
    
    #include "Enemy.h"
    #include "Hero.h"
    
    using namespace std;
    
    int main()
    {
        Defiler defOne;
        cout << defOne.getHp();
        Blood noOne;
        cout << endl << noOne.getHp();
        noOne.setHp(10);
        cout << endl << noOne.getHp();
        Warrior warOne;
        warOne.atk(defOne, warOne);
        cin.get();
        
    return 0;    
    }
    When I try to compile it, I get these errors:

    4 C:\RPG\main.cpp In file included from main.cpp
    10 C:\RPG\Enemy.h variable or field `atk' declared void
    10 C:\RPG\Enemy.h expected `;' before '(' token
    Weird thing is, the enemy atk() seems to be the problem, yet it seems to me like there should be nothing wrong with it, as the hero atk() works fine.

    Help !!

  11. #11
    Registered User stillwell's Avatar
    Join Date
    Aug 2004
    Posts
    80
    Anyone? All help is much appreciated.

  12. #12
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Hi,

    You can't use a name in your program--unless you first introduce the name in a declaration or definition.
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
    The compiler sees the name Hero, but it hasn't been declared or defined previously. Including Hero.h won't work:
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    #include "Hero.h"
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
    When you include a file, the contents of the file just replace the include statement, so you would have:
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    class Hero
    {
    public:
           
           void atk(Enemy& anEnemy, Hero& aHero);
    	   
    	   ...
    }
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
    And then you have a similar problem. The compiler sees the name Enemy:
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    class Hero
    {
    public:
           
           void atk(Enemy& anEnemy, Hero& aHero);
    	   
    	   ...
    }
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
    but Enemy hasn't been declared or defined previously. The way you get around the circular reference problem is by using what's called a 'forward declaration':
    Code:
    #ifndef ENEMY_H
    #define ENEMY_H
    
    #include <iostream>
    
    class Hero;
    
    class Enemy
    {
    public:
           
           void atk(Hero& aHero, Enemy& anEnemy);
    A forward declaration declares the name to the compiler and promises that Enemy will be fully declared somewhere else.
    Last edited by 7stud; 04-02-2006 at 09:39 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 06-08-2009, 03:03 PM
  2. Inheritance and program structure planning please help a newbie
    By ninjacookies in forum C++ Programming
    Replies: 1
    Last Post: 10-23-2005, 12:18 PM
  3. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 08:04 AM
  4. inheritance and performance
    By kuhnmi in forum C++ Programming
    Replies: 5
    Last Post: 08-04-2004, 12:46 PM
  5. Inheritance vs Composition
    By Panopticon in forum C++ Programming
    Replies: 11
    Last Post: 01-20-2003, 03:41 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21